Приведенный ниже код перезапускает функцию read()
если она не работает из-за прерывания по сигналу. read()
возобновляет чтение с того места, где оно было прервано. Итак, если read()
прерывается перед чтением символа EOF
, что он вернет, сколько байтов оно прочитало?
int r_read(int fd, void *buf, int size) { while((retval=read(fd,buf,size))==-1 && errno ==EINTR); return retval; }
С уважением.
Вот почему количество прочитанных байтов должно храниться как общее, чтобы избежать проблем с прерываниями. Это также полезно для неблокирующего ввода-вывода.
{ int ret = 0, nread; char *nbuf = (char *) buf; while ((nread = read(fd, nbuf, size)) != 0) { if (nread > 0) ret += nread, nbuf += nread, size -= nread; elif (errno != EINTR) break; } return ret; }
Если errno == EINTR
, это означает, что read
было прервано, прежде чем он мог читать любые данные в соответствии с man
страницей. Т.е. из моего чтения это как если бы read
со статусом EINTR
просто не происходило до данных в streamе. Поэтому кажется, что вы можете просто повторить попытку, не беспокоясь о том, что потеряли все байты. Я нахожу это немного удивительным, и я на самом деле не тестировал его, но это то, что говорится в руководстве.
Вот фактический текст с man-страницы:
EINTR Вызов прерывался сигналом перед чтением любых данных; см. сигнал (7).
Edit: Я проверил это сейчас, и я обнаружил, что если бы я прервал чтение, EINTR
был бы возвращен, только если чтение было прервано до того, как все было прочитано. В противном случае он вернется успешно, прочитав меньше запрошенного количества байтов. Таким образом, чтобы получить нужное количество байтов, вам потребуется что-то, что перезапускается, как указывает другой ответ.
В этом нет «символа EOF», есть условие конца файла, которое указывается как чтение 0 байтов. Ошибка EINTR устанавливается только в том случае, если read
прерывается, ожидая чего-то, то есть до того, как базовый ресурс произведет какие-либо данные.
Поскольку EOF обычно вызывает read
чтобы остановить ожидание и вернуть значение, read
не может быть прервано, и если это произойдет, оно просто вернет то, что у него есть, – индикатор EOF. Если read
прерывается, ожидая EOF (до того, как он будет объявлен базовым ресурсом), он, естественно, вернет -1 и установит EINTR.