linux – 如何确定是否可以写入管道

前端之家收集整理的这篇文章主要介绍了linux – 如何确定是否可以写入管道前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有没有办法(在C中,或最好在Perl中)确定是否可以写入命名管道 – 即有一个有效的读取过程
似乎如果我打开写入非阻塞,open会立即返回,但select for write也会立即返回.
目标是如果读取结束尚未准备好,则写入过程仅进行(即跳过发送)

解决方法

有可能你没有注意打开的返回码.如果打开FIFO进行写入和非阻塞,则有两种可能的结果.

>如果已有读卡器,则打开将立即成功返回.
>如果没有管道读取器,则打开将失败并显示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没有阻塞就失败的事实并不是那么有用.关于你唯一能做的就是不断尝试打开,直到你成功,这种轮询可能是浪费,而在长期运行程序的情况下等待间歇性读者是有点荒谬的.

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

>如果在select语句中使用FIFO写入fd,它总是可写的……直到它不可写.也就是说,因为您也是自己的读取器,所以FIFO写入将成功,直到您使用PIPE_BUF字节填充FIFO缓冲区.之后,FIFO将无法写入,并且您的写入将在EAGAIN中失败,直到合法读取器(即非您自己)出现,打开以进行读取,并开始耗尽缓冲区.
>通过打开自己的FIFO进行读写,当合法用户关闭FIFO时,您将看不到EOF.由于您只关心写作,这对您来说可能不是问题.

我从未尝试过的另一种可能的解决方案是在FIFO上使用inotify.您可以在选择中监视inotify文件描述符,并确定何时有人打开FIFO.然后你知道你可以安全地开始写作.您可能希望屏蔽FIFO上的打开权限,以便您可以成为唯一的编写者,如果可能的话,您的应用程序.

对于这些时髦的语义,FIFO应该被重命名为PITA.如果你能做出改变,这就是为什么Unix众神赋予我们凡人的域名套接字.

原文链接:https://www.f2er.com/linux/395016.html

猜你在找的Linux相关文章