编程语言
首页 > 编程语言> > c – 打开mkfifo-ed管道时为什么程序会挂起?

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