C语言 如何查看管道是否为空

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13811614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:43:17  来源:igfitidea点击:

How to see if a pipe is empty

cblockpipeblocking

提问by darkpbj

Assuming a pipe,

假设一个管道,

int pipe_fd[2];
pipe(pipe_fd);

We fork, and expect that one process will write into the pipe at an arbitrary time. In one of the processes, we want to be able to check the contents of the pipe without blocking.

我们分叉,并期望一个进程在任意时间写入管道。在其中一个进程中,我们希望能够在不阻塞的情况下检查管道的内容。

i.e. While a typical read will block if nothing is present and the write end remains open. I want to go do other stuff and potentially even read a bit at a time, do some stuff, and then check back to see if there's more, a la:

即,如果没有任何东西存在并且写入端保持打开状态,则典型的读取将阻塞。我想去做其他事情,甚至可能一次读一点,做一些事情,然后再回来看看是否还有更多,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
}

采纳答案by R.. GitHub STOP HELPING ICE

Your logic is wrong in that readwill not return 0 when it runs out of characters; instead, it will block until it receives more, unless you put the file in non-blocking mode, but then it will return -1 and set errnoto EWOULDBLOCKor EAGAINrather than returning 0. The only time readcan everreturn 0 is when the size argument was 0 or end-of-file has been reached. And, for pipes, end-of-file means the writing end of the pipe has been closed; end-of-file status does not occur just because there's not any input available yet.

你的逻辑是错误的,read当字符用完时不会返回 0;相反,它会阻止,直到它接收更多的,除非你把非阻塞模式的文件,但随后会返回-1,并设置errnoEWOULDBLOCKEAGAIN而不是返回0,只有时间read永远返回0是当尺寸参数为0 或已到达文件结尾。并且,对于管道,文件结束意味着管道的写入端已经关闭;文件结束状态不会仅仅因为没有任何可用的输入而发生。

With that said, the simplest way to check is:

话虽如此,最简单的检查方法是:

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

but unless you're using nonblocking mode, you'll need to make this check before every single read operation. Passing a larger buffer to readrather than doing it a byte-at-a-time would eliminate most of the cost of checking.

但是除非您使用非阻塞模式,否则您需要在每次读取操作之前进行此检查。传递一个更大的缓冲区read而不是一次一个字节将消除大部分检查成本。

回答by 7heo.tk

You can check if there is data to be read with the read()function. From read(3):

您可以使用该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.

So if you set O_NONBLOCK, you will be able to tell if something is to be read on the pipe, by simply calling read().

因此,如果您设置了O_NONBLOCK,您将能够通过简单地调用 来判断是否要在管道上读取某些内容read()

As a reminder, from open(3):

提醒一下,来自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 [...]

I hope it helps.

我希望它有帮助。

回答by hippiemancam

R..'s answer is good however poll returns the number of file descriptor structs that have flags set in "revents". This will be 1 if you can read from fdbut will also be 1 if any of the error flags are set. This means R..'s answer will say the pipe is readable if it ever enters an error state. A more robust check could be something like this:

R.. 的回答很好,但是 poll 返回在“revents”中设置了标志的文件描述符结构的数量。如果您可以读取,则为 1,fd但如果设置了任何错误标志,则为 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;
}