如何向命名管道写入数据并且不等待读取管道。

3
我正在向管道写入内容,直到用户输入字符串“end”。如果用户输入字符串“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) ... 报告错误并停止... },然后只需要一份 open()write() 的副本。你应该考虑如果 FIFO 创建失败会发生什么。你应该考虑如果 open() 失败会发生什么。你可能需要考虑检查 write() 的返回值。除非你成功打开了 fd,否则不要调用 close()(但是关闭应该在循环中与打开一起;你正在泄漏文件描述符)。你确定要在循环中打开 FIFO 吗? - Jonathan Leffler
2个回答

1

命名管道不是合适的工具,因为没有提供以非阻塞模式使用它们的方法。

您可以使用编程语言编写类似于cat但不会阻塞的工具。但我找到的结果都不够满意,无法向您推荐。

否则只能使用套接字(使用netcatlocalhost),但这种方式很不安全,因为您计算机上的其他用户也可以访问它们...

或者使用一种正常文件作为缓冲区。但您将面临如何删除已读取的行以避免洪泛、竞争条件等问题。

很抱歉,这里真的没有一个好的解决方案。要正确解决这个问题,需要打补丁来添加一个选项,以允许非阻塞行为。


1

来自mkfifo(3)手册页面:

但是,在您可以继续执行任何输入或输出操作之前,它必须同时在两端打开。为读取而打开FIFO通常会阻塞,直到某个其他进程为写入打开相同的FIFO,反之亦然。

上面的段落意味着write将阻塞,直到有人从FIFO中读取,这就是您在程序中看到的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接