web-dev-qa-db-ja.com

パイプが空かどうかを確認する方法

パイプを想定して、

int pipe_fd[2];
pipe(pipe_fd);

フォークして、1つのプロセスが任意の時間にパイプに書き込むことを期待します。あるプロセスでは、パイプの内容をブロックせずにチェックできるようにする必要があります。

つまり、通常の読み取りは、何も存在せず、書き込み終了が開いたままの場合にブロックされます。私は他のことをしたいのですが、一度に少しずつ読んで、いくつかのことをしてから、もう一度チェックして、もっとあるかどうかを確認したいと思います。

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
}
11
darkpbj

readが文字を使い果たしても0を返さないという点で、ロジックが間違っています。代わりに、ファイルを非ブロックモードにしない限り、さらに受信するまでブロックしますが、その後-1を返し、errnoEWOULDBLOCKまたはEAGAINに設定します。 0を返すのではなく。readever 0を返すことができるのは、size引数が0であるか、ファイルの終わりに達したときだけです。そして、パイプの場合、ファイルの終わりは、パイプの書き込み終了が閉じられたことを意味します。利用可能な入力がまだないという理由だけで、ファイルの終わりステータスは発生しません。

そうは言っても、チェックする最も簡単な方法は次のとおりです。

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

ただし、ノンブロッキングモードを使用している場合を除き、すべての読み取り操作の前にこのチェックを行う必要があります。一度に1バイトずつ行うのではなく、より大きなバッファをreadに渡すと、チェックのコストのほとんどが排除されます。

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 [...]
_

お役に立てば幸いです。

4
7heo.tk

R ..の答えは良いですが、pollは、「revents」にフラグが設定されているファイル記述子構造体の数を返します。 fdから読み取ることができる場合は1になりますが、エラーフラグのいずれかが設定されている場合も1になります。これは、R ..の答えは、パイプがエラー状態になった場合に読み取り可能であると言うことを意味します。より堅牢なチェックは次のようになります。

bool canReadFromPipe(){
    //file descriptor struct to check if POLLIN bit will be set
    //fd is the file descriptor of the pipe
    struct pollfd fds{ .fd = fd, .events = POLLIN };
    //poll with no wait time
    int res = poll(&fds, 1, 0);

    //if res < 0 then an error occurred with poll
    //POLLERR is set for some other errors
    //POLLNVAL is set if the pipe is closed
    if(res < 0||fds.revents&(POLLERR|POLLNVAL))
    {
        //an error occurred, check errno
    }
    return fds.revents&POLLIN;
}
1
hippiemancam