我使用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;
}
答案 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
...
只读,没有O_NONBLOCK
:open
阻塞,直到另一个进程打开FIFO进行写入。将fopen
与模式参数"r"
一起使用时,这是一种行为。
只写,没有O_NONBLOCK
:open
阻塞,直到另一个进程打开FIFO进行读取。将fopen
与模式参数"w"
一起使用时,这是一种行为。
只读,O_NONBLOCK
:open
会立即返回。
只写,O_NONBLOCK
:open
返回错误,errno
设置为ENXIO
,除非另一个进程打开FIFO进行读取。
来自W. Richard Stevens的“UNIX环境中的高级编程”的信息。 功能
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)
进程阻塞,直到管道的另一端打开。