c – 打开mkfifo-ed管道时为什么程序会挂起?
作者:互联网
我使用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;
}
解决方法:
尝试将“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打开:
$strace -P /tmp/myFIFO ./a.out
open("/tmp/myFIFO", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...
关于如何打开FIFO的一些背景知识
只读,没有O_NONBLOCK:打开块,直到另一个进程打开FIFO进行写入.这是使用fopen与模式参数“r”时的行为.
只写,没有O_NONBLOCK:打开块,直到另一个进程打开FIFO进行读取.这是使用fopen与模式参数“w”时的行为.
只读,带O_NONBLOCK:open立即返回.
只写,使用O_NONBLOCK:open会返回错误,并将errno设置为ENXIO,除非另一个进程打开FIFO进行读取.
来自W. Richard Stevens的“UNIX环境中的高级编程”的信息.
打开FIFO进行读写
Linux也可以在同一个进程中打开FIFO进行读写. Linux FIFO man page指出:
Under Linux, opening a FIFO for read and write will succeed both in
blocking and nonblocking mode. POSIX leaves this behavior undefined.
This can be used to open a FIFO for writing while there are no readers
available. A process that uses both ends of the connection in order
to communicate with itself should be very careful to avoid deadlocks.
这是一个写入和读取同一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之外的操作系统上运行.
标签:c-3,c,mkfifo 来源: https://codeday.me/bug/20190923/1813686.html