LINUX.ORG.RU

Обработка прерванного вызова функции EINTR

 ,


0

1

Здравствуйте.

есть вот такой код

ssize_t ret;
while (len != 0 && (ret = read (fd, buf, len)) != 0) {
    if (ret == –1) {
        if (errno == EINTR)
               continue;
        perror ("read");
        break;
   }
len -= ret;
buf += ret;
}

и следующее описание

В этом фрагменте кода обрабатываются все пять условий. Цикл считывает len байт с актуальной файловой позиции, равной значению fd , и записывает их в buf. Разумеется, значение buf должно быть как минимум равно значению len . Чтение продолжается, пока не будут получены все len байт или до достижения конца фай­ла. Если прочитано ненулевое количество байтов, которое, однако, меньше len, то значение len уменьшается на количество прочитанных байтов, buf увеличивается на то же количество и вызов повторяется. Если вызов возвращает –1 и значение errno , равное EINTR, то вызов повторяется без обновления параметров. Если вызов возвращает –1 с любым другим значением errno, вызывается perror(). Он выводит описание возникшей проблемы в стандартную ошибку, и выполнение цикла пре­кращается. пробую этот код запустить(упрощенный вариант):

int main()
{	
    ssize_t ret;
    int buf[16];
    int len = 16;

    int fd;
    fd = open("./data", O_RDONLY);

    while (len != 0 && (ret = read (fd, buf, len)) != 0)
    {
        if (ret == -1)
        {
            if (errno == EINTR)	continue;
            perror ("read");
            break;
	}
        
        printf("%s", buf);
	len -= ret;
	buf += ret;
    }
}

как я полагаю: buf - 16 байт, len - 16 байт, те мы считываем из fd 16 байт (len), в буфер buf, который тоже 16 байт. непонятно как буфер

buf увеличивается на то же количество

считываем мы по 16 байт, потом считали 10, допустим, и зачем нам увеличивать буфер (и как его увеличивать?) и уменьшать длину (len). Если read прервали, то мы просто считываем заново - continue… не «догоняю» момент с изменеием len и buf


Во-первых, это так не работает, особенно c int (потому что read() принимает буфер байтов и длину в байтах, а int[16] [обычно] занимает больше, чем 16 байтов). Так что int => uint8_t.

buf должен быть указателем на начало заполняемого буфера. Когда к нему что-то прибавляется — это не буфер увеличивается, а указатель сдвигается. Если read() считал всё, что попросили — работа закончена. Если только часть — buf перемещается в незаполенную часть буфера, а len соответствующим образом уменьшается, чтобы содержать длину оставшейся незаполненной части.

На входе:

[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 ^
buf

len == 16

Частичный успех read(fd, buf, len):

ret == 10

[X][X][X][X][X][X][X][X][X][X][ ][ ][ ][ ][ ][ ]
 ^
buf

len == 16

Теперь сдвигаем на считанные 10 байтов:

buf += ret;
len += ret;

[X][X][X][X][X][X][X][X][X][X][ ][ ][ ][ ][ ][ ]
                               ^
                              buf

len == 6

и read(fd, buf, len) читает оставшиеся шесть в оставшееся место.

ilammy ★★★
()
Ответ на: комментарий от Snorri

грубо.

#define SZ 16
int main()
{	
    ssize_t ret;
    int buf[SZ],
        len = SZ,
        fd = open("./data", O_RDONLY);

    for(;len>0 &&(ret = read(fd, buf+SZ-len, len)) != 0;len-=ret){
        if (ret == -1)&&(errno == EINTR) continue;
        if (ret == -1) return (int)perror("read");
        printf("%s", buf+SZ-len);
    }
}
qulinxao3 ★★
()
Ответ на: комментарий от qulinxao3
#define SZ 16
int main()
{	
    ssize_t ret;
    for(int fd = open("./data", O_RDONLY),len = SZ,buf[SZ];
        len>0 &&(ret = read(fd, buf+SZ-len, len)) != 0;
        len-=ret){
          if (ret == -1)&&(errno == EINTR) continue;
          if (ret == -1) return (int)perror("read");
          printf("%s", buf+SZ-len);
    }
}
qulinxao3 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.