C - Как видеть, что труба пуста

при условии, что труба,

    int pipe_fd[2];
    pipe(pipe_fd);

Мы видим, что один процесс будет записываться в трубу в произвольное время. В одном из процессов мы хотим иметь возможность проверять содержимое трубы без блокировки.

то есть. Хотя типичное чтение будет блокироваться, если ничего не присутствует, и конец записи остается открытым. Я хочу пойти делать другие вещи и, возможно, даже немного почитать немного, сделать некоторые вещи, а затем проверить, чтобы увидеть, есть ли еще, a la:

    close(pipe_fd[1]);

    while(1){
        if(/**Check pipe contents**/){
            int present_chars = 0;    

            while( read(pipe_fd[0],&buffer[present_chars],1) != 0)
                ++present_chars;

            //do something

        }
        else
            //do something else
    }

Спасибо заранее!

Ответ 1

Ваша логика ошибочна в том, что read не вернет 0, когда закончится символ; вместо этого он будет блокироваться до тех пор, пока он не получит больше, если вы не поместите файл в неблокирующий режим, но затем он вернет -1 и установите errno в EWOULDBLOCK или EAGAIN вместо того, чтобы возвращать 0. Единственное время read может когда-либо возвращать 0, когда аргумент размера был равен 0 или конец файла. И для труб конец файла означает, что конец записи трубы закрыт; статус конца файла не возникает только потому, что еще нет доступных данных.

С учетом сказанного, самый простой способ проверить:

if (poll(&(struct pollfd){ .fd = fd, .events = POLLIN }, 1, 0)==1) {
    /* data available */
}

но если вы используете неблокирующий режим, вам необходимо выполнить эту проверку перед каждой отдельной операцией чтения. Передача большего буфера в read вместо того, чтобы делать это, byte-at-time устранит большую часть затрат на проверку.

Ответ 2

Вы можете проверить, есть ли данные для чтения с помощью функции read(). От read(3):

When attempting to read from an empty pipe or FIFO:

* If some process has the pipe open for writing and
O_NONBLOCK is set, read() shall return -1 and set
errno to [EAGAIN].

* If some process has the pipe open for writing and
O_NONBLOCK  is  clear,  read() shall block the calling
thread until some data is written or the pipe is
closed by all processes that had the pipe open for
writing.

The read() function shall fail if:

EAGAIN or EWOULDBLOCK

    The file descriptor is for a socket, is marked
    O_NONBLOCK, and no data is waiting to be received.

Итак, если вы установите O_NONBLOCK, вы сможете сказать, что что-то нужно читать на трубе, просто называя read().

Напоминаем, что от open(3):

SYNOPSIS
    int open(const char *path, int oflag, ...  );

DESCRIPTION
    Values for oflag are constructed by a
    bitwise-inclusive OR of flags from the following
    list, defined in <fcntl.h>. Applications shall
    specify exactly one  of  the first three values
    (file access modes) below in the value of oflag:

    O_NONBLOCK [...]

Надеюсь, это поможет.