如何写入命名管道而不等待读取管道

Posted

技术标签:

【中文标题】如何写入命名管道而不等待读取管道【英文标题】:how to write to a named pipe and don't wait for reading the pipe 【发布时间】:2012-09-04 13:33:09 【问题描述】:

我正在写入管道,直到用户输入字符串“end”。如果用户输入字符串“end”,我想更进一步。在这里,我必须关闭管道并打印消息“写入管道后”。但是即使我输入了“结束”字符串,它也没有打印“写入管道后”行。即使没有读取管道的过程,我如何关闭管道并走得更远?..

您好,这是我的代码。,

int main() 
int fd;
char *b, *c;
printf("Enter Str : ");
b = malloc(50);
gets(b);

while(strcmp(b,"end")!=0)
    if(access("MSG",F_OK) != -1)    // check pipe is already available.
    
        fd = open("MSG", O_WRONLY);
        write(fd, b, strlen(b) );
    
    else
    
        if( mkfifo("MSG", 0666) != -1)  // create pipe if not available.
        
            fd = open("MSG", O_WRONLY);
            write(fd, b, strlen(b) );               
        
    
    printf("Enter Str : ");
    gets(b);
   
close(fd);
printf("After Written to Pipe");


【问题讨论】:

那里有一大块(不必要的)代码重复。您可以使用if (access("MSG", F_OK) != 0) if (mkfifo("MSG", 0666) != 0) ... report error and stop... ,然后拥有一份open()write()。您应该考虑如果 FIFO 创建失败会发生什么。您应该考虑如果open() 失败会发生什么。您可能会考虑检查来自write() 的返回值。除非您成功打开 fd,否则不应调用 close()(但关闭应该在打开的循环中;您正在泄漏文件描述符)。您确定要在循环中打开 FIFO 吗? 【参考方案1】:

来自mkfifo(3) 手册页:

但是,它必须同时在两端打开,然后才能继续对其进行任何输入或输出操作。打开一个 FIFO 进行读取通常会阻塞,直到其他进程打开同一个 FIFO 进行写入,反之亦然。

上述段落表示write 将阻塞,直到有人从 FIFO 中读取,这就是您在程序中看到的。

【讨论】:

【参考方案2】:

命名管道在这里不是合适的工具,因为bash 无法在非阻塞模式下使用它们。

可以使用类似于cat 的编程语言编写工具,但不会阻塞。但是none of the results I found 让我很高兴向您推荐它们。

否则它是套接字(使用netcatlocalhost),不幸的是,它是不安全的,因为您计算机上的所有其他用户也可以访问它们......

或某种充当缓冲区的普通文件。但是您会遇到如何删除已阅读的行以使其不会泛滥的问题,以及竞争条件以及所有那些噩梦。

很抱歉,这里确实没有好的解决方案。要以正确的方式解决此问题,需要修补 bash 和 cat 以添加允许非阻塞行为的选项。

【讨论】:

以上是关于如何写入命名管道而不等待读取管道的主要内容,如果未能解决你的问题,请参考以下文章

在断开连接之前等待读取命名管道

我的 C++ 程序如何等到对命名管道进行新的写入?

Java中的命名管道和多线程

Windows上的PHP命名管道

如何避免命名管道中的多个作者?

为啥 bash 在写入命名管道时关闭?