Нужно ли использовать while l oop при использовании системных вызовов read и write? - PullRequest
0 голосов
/ 04 мая 2020

Я практикую системный вызов чтения и записи, приведенный ниже код работает нормально некоторое время l oop, а также без них. Подскажите, пожалуйста, в чем здесь польза while l oop, нужно ли его добавлять при использовании системных вызовов read и write. Я начинающий. Спасибо.

#include <unistd.h>
#define BUF_SIZE 256
int main(int argc, char *argv[])
{
    char buf[BUF_SIZE];    
    ssize_t rlen;
    int i; 
    char from;
    char to;
    from = 'e';
    to = 'a';

    while (1) {
        rlen = read(0, buf, sizeof(buf));
        if (rlen == 0)
               return 0;

        for (i = 0; i < rlen; i++) {
               if (buf[i] == from)
                      buf[i] = to;
        }
    write(1, buf, rlen);
   }
return 0;
}


1 Ответ

1 голос
/ 04 мая 2020

Обычно вам нужно использовать while петли (или вообще какой-то тип l oop) с read и write, потому что, как вы должны знать на странице руководства (man 2 read) ):

RETURN VALUE

On success, the number of bytes read is returned (zero indicates end
of file), and the file position is advanced by this number.  It is
not an error if this number is smaller than the number of bytes
requested; this may happen for example because fewer bytes are
actually available right now (maybe because we were close to end-of-
file, or because we are reading from a pipe, or from a terminal), or
because read() was interrupted by a signal.  See also NOTES.

Поэтому, если вы хотите прочитать больше 1 байта, вам нужно сделать это в al oop, потому что read всегда может процесс меньше , чем запрашиваемая сумма.

Аналогично, write также может обрабатывать меньше, чем запрошенный размер (см. man 2 write):

RETURN VALUE

On success, the number of bytes written is returned (zero indicates nothing was written).  It is not an error  if  this
number  is  smaller than the number of bytes requested; this may happen for example because the disk device was filled.
See also NOTES.

On error, -1 is returned, and errno is set appropriately.

Единственная разница здесь, когда write возвращает 0, это не ошибка или индикатор конца файла, вы должны просто повторить запись.

Ваш код почти правильный, поскольку он использует al oop продолжать чтение, пока не останется больше байтов для чтения (когда read возвращает 0), но есть две проблемы:

  1. Вы должны проверять ошибки после read (rlen < 0).
  2. Когда вы используете write, вы также должны добавить туда al oop, потому что, как я только что сказал, даже write может обработать меньше запрошенного количества байтов.

Правильная версия вашего кода будет:

#include <stdio.h>
#include <unistd.h>

#define BUF_SIZE 256

int main(int argc, char *argv[])
{
    char buf[BUF_SIZE];
    ssize_t rlen, wlen, written;
    char from, to;
    int i;

    from = 'e';
    to = 'a';

    while (1) {
        rlen = read(0, buf, sizeof(buf));

        if (rlen < 0) {
            perror("read failed");
            return 1;
        } else if (rlen == 0) {
            return 0;
        }

        for (i = 0; i < rlen; i++) {
            if (buf[i] == from)
                buf[i] = to;
        }

        for (written = 0; written < rlen; written += wlen) {
            wlen = write(1, buf + written, rlen - written);

            if (wlen < 0) {
                perror("write failed");
                return 1;
            }
        }
    }

    return 0;
}
...