如何确定管道是否可以写入 [英] how to determine if pipe can be written

查看:133
本文介绍了如何确定管道是否可以写入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种方法(在C中,或者最好在Perl中)来确定是否可以写入命名管道-即,存在活动的读取过程 看来,如果我打开以进行写非阻塞操作,则打开会立即返回,但写入选择也会立即返回. 目的是在阅读端未准备好的情况下进行书写过程(即跳过发送)

Is there a way (in C, or preferably in Perl) to determine whether a named pipe may be written - i.e. there is an active reading process It seems that if I open for write nonblocking, the open returns at once but a select for write also returns immediately. The goal is for the writing process to just carry on (i.e. skip sending) if the reading end is not ready

推荐答案

可能是您没有注意open中的返回代码.如果打开FIFO以将写入为非阻塞状态,则有两种可能的结果.

Chances are that you are not paying attention to the return codes from open. If you open a FIFO for writing and as non-blocking there are two possible outcomes.

  1. 如果已经有阅读器,则open将立即成功返回.

如果没有管道读取器,则open将失败,并显示errno = ENXIO.

If there is no pipe reader the open will fail with errno = ENXIO.

以下程序演示.

#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<stdlib.h>
#include <sys/stat.h>

#define SERVFIFO "/tmp/server.fifo"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

void syserr(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc, char** argv)
{
    umask(0);

    if (mkfifo(SERVFIFO, FILE_MODE) < 0 && errno != EEXIST)
        syserr("mkfifo");

    // try to open for write with no readers

    int fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
    if (fdw == -1)
        perror("non-blocking open for write with no readers failed");

    // create a reader - the process itself - non-blocking

    int fdr = open(SERVFIFO, O_RDONLY | O_NONBLOCK);
    if (fdr == -1)
        syserr("non-blocking open for read no writers failed");

    // try again to open for write but this time with a reader
    fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
    if (fdw == -1)
        syserr("non-blocking open with readers failed");

    printf("non-blocking open for write succeeded\n");

    close(fdw);
    close(fdr);
    unlink(SERVFIFO);
}

也就是说,open在没有阻止的情况下失败的事实并没有那么有用.关于您唯一能做的就是不断尝试打开,直到成功为止,并且这种轮询可能是浪费的,并且在长时间运行的程序中,等待间歇性读取器的行为有点荒谬.

That said, the fact that the open fails without blocking isn't all that useful. About the only thing you can do is continually try to open until you succeed and that kind of polling can be wasteful, and in the context of a long running program waiting for intermittent readers is sort of ridiculous.

一种解决方案是上面使用的解决方案-打开FIFO读取自己-但这有其自身的问题.

One solution is that used above - open the FIFO for reading yourself - but this has its own problems.

  1. 如果在select语句中使用FIFO写fd,它将始终是可写的,直到不是.也就是说,由于您也是您自己的读取器,因此FIFO写入将成功,直到您用PIPE_BUF字节填充FIFO缓冲区为止.此后,FIFO将不可写,并且使用EAGAIN的操作将失败,直到出现合法的读取器(即不是您自己),打开读取并开始清空缓冲区为止.

  1. If you use your FIFO write fd in your select statement it is always going to be writable...until it isn't. That is, because you are your own reader too, the FIFO writes will succeed until you fill the FIFO buffer with PIPE_BUF bytes. After that the FIFO won't be writable and your writes will fail with EAGAIN until a legitimate reader (i.e. not yourself) comes along, opens for reading, and starts draining the buffer.

通过打开自己的FIFO进行读写,当合法用户关闭FIFO时,他们不会看到EOF.由于您只关心编写,所以这对您来说可能不是问题.

By opening your own FIFO for reading and writing, you won't see an EOF from legitimate users when they close the FIFO. Since you are only concerned about writing this may not be an issue for you.

另一个我从未尝试过的可能解决方案是在您的FIFO中使用 inotify .您可以在select中监视inotify文件描述符,并确定何时有人打开了FIFO.然后,您就知道可以放心写作了.您可能希望屏蔽FIFO上的打开权限,以便在可能的情况下成为唯一的写程序.

Another possible solution, which I have never tried, is to use inotify on your FIFO. You can monitor the inotify file descriptor in your select and determine when someone has opened the FIFO. Then you know you can safely open your end for writing. You would probably want to mask off open permissions on the FIFO so that you can be the only writer, if possible for your application.

FIFO重命名为PITA.如果可以进行更改,这就是Unix之神将域套接字赋予我们凡人的原因.

FIFOs should be renamed PITAs for these funky semantics. If you can make the change, this is why the Unix gods bestowed domain sockets upon us mere mortals.

这篇关于如何确定管道是否可以写入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆