为什么我的程序在打开mkfifo-ed管道时会挂起?

时间:2011-12-14 16:17:23

标签: c++ c mkfifo

我使用mkfifo创建命名管道。 然后我使用以下程序打开它。但是,该程序挂起在“fopen”行。这里有什么问题吗?

int main(int argc, char** argv) {
char* line = "hello, world!";
FILE* fp = fopen("/tmp/myFIFO", "rw");
fprintf(fp, line);
fclose(fp);
return 0;
}

2 个答案:

答案 0 :(得分:16)

尝试将"w"作为模式传递给fopen。 "rw"不是fopen的有效模式参数,即使它是,您可能不希望在同一过程中同时读取和写入FIFO(尽管可能,请参见下文) )。

另外,打开文件进行读写的正确模式参数可以是"r+""w+"(参见this question for the differences的答案)。 功能

该程序将正确写入FIFO:

#include <stdio.h>
int main(int argc, char** argv) {
    FILE* fp = fopen("/tmp/myFIFO", "w");
    fprintf(fp, "Hello, world!\n");
    fclose(fp);
    return 0;
}

请注意,上述程序中的fopen将一直阻塞,直到打开FIFO进行读取。当它阻塞时,在另一个终端运行:

$ cat /tmp/myFIFO
Hello, world!
$ 

它阻止的原因是因为fopen未将O_NONBLOCK传递给open

$ strace -P /tmp/myFIFO ./a.out
open("/tmp/myFIFO", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...

关于如何打开FIFO的一些背景

只读,没有O_NONBLOCKopen阻塞,直到另一个进程打开FIFO进行写入。将fopen与模式参数"r"一起使用时,这是一种行为。

只写,没有O_NONBLOCKopen阻塞,直到另一个进程打开FIFO进行读取。将fopen与模式参数"w"一起使用时,这是一种行为。

只读,O_NONBLOCKopen会立即返回。

只写,O_NONBLOCKopen返回错误,errno设置为ENXIO,除非另一个进程打开FIFO进行读取。

来自W. Richard Stevens的“UNIX环境中的高级编程”的信息。 功能

打开FIFO以进行读取写入

Linux也可以在同一个进程中打开FIFO进行读写。 Linux FIFO man page州:

  

在Linux下,打开FIFO进行读写将同时成功   阻塞和非阻塞模式。 POSIX未定义此行为。   这可用于在没有读卡器的情况下打开FIFO进行写入   可用。按顺序使用连接两端的进程   与自己沟通应该非常小心,以避免死锁。

这是一个向同一个FIFO写入和读取的程序:

#include <stdio.h>
int main(int argc, const char *argv[]) {
    char buf[100] = {0};
    FILE* fp = fopen("/tmp/myFIFO", "r+");
    fprintf(fp, "Hello, world!\n");
    fgets(buf, sizeof(buf), fp);
    printf("%s", buf);
    fclose(fp);
    return 0;
}

它不会阻止,并立即返回:

$ gcc fifo.c && ./a.out 
Hello, world!

请注意,这不是可移植的,并且可能无法在除Linux之外的操作系统上运行。

答案 1 :(得分:9)

进程阻塞,直到管道的另一端打开。