我使用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;
}
Run Code Online (Sandbox Code Playgroud)
Tim*_*Tim 18
尝试将"w"模式传递给fopen."rw"不是有效的模式参数fopen,即使它是,你可能不希望在同一个过程中同时读写FIFO(尽管有可能,见下文).
顺便说一下,为读取和写入打开文件的正确模式参数是"r+"或者"w+"(对于差异,请参阅此问题的答案).
该程序将正确写入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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,fopen在上述程序中将阻塞,直到打开FIFO进行读取.当它阻塞时,在另一个终端运行:
$ cat /tmp/myFIFO
Hello, world!
$
Run Code Online (Sandbox Code Playgroud)
它阻塞的原因是因为fopen没有传递O_NONBLOCK给open:
$ strace -P /tmp/myFIFO ./a.out
open("/tmp/myFIFO", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...
Run Code Online (Sandbox Code Playgroud)
只读,不带O_NONBLOCK:open阻塞,直到另一个进程打开FIFO进行写入.这是使用fopenwith mode参数时的行为"r".
只写,不带O_NONBLOCK:open阻塞,直到另一个进程打开FIFO进行读取.这是使用fopenwith mode参数时的行为"w".
只读,带O_NONBLOCK:open立即返回.
只写,带O_NONBLOCK:open返回errno设置为的错误,ENXIO除非另一个进程打开FIFO进行读取.
来自W. Richard Stevens的"UNIX环境中的高级编程"的信息.
Linux也可以在同一个进程中打开FIFO进行读写.在Linux的FIFO手册页指出:
在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;
}
Run Code Online (Sandbox Code Playgroud)
它不会阻塞,并立即返回:
$ gcc fifo.c && ./a.out
Hello, world!
Run Code Online (Sandbox Code Playgroud)
请注意,这不是可移植的,并且可能无法在Linux之外的操作系统上运行.