我创建了一个FIFO,写入并取消链接。 令我惊讶的是,我能够在取消链接后从fifo中读取数据,为什么会这样?
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUF 256
int main()
{
int fd;
char * myfifo = "/tmp/myfifo";
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
int pid = fork();
if (pid != 0)
{
/* write "Hi" to the FIFO */
fd = open(myfifo, O_WRONLY);
write(fd, "Hi", sizeof("Hi"));
close(fd);
/* remove the FIFO */
unlink(myfifo);
}
else
{
wait(NULL);
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
close(fd);
return 0;
}
return 0;
}
答案 0 :(得分:1)
除非您将O_NONBLOCK
标志传递给open(2)
,否则打开FIFO会阻塞,直到另一端打开。来自man 7 fifo
:
必须在数据之前打开FIFO(读取和写入) 可以通过。通常,打开FIFO块直到另一端 也开了。
进程可以在非阻塞模式下打开FIFO。在这种情况下,打开 即使没有人在写入端打开,只读也会成功 然而,只有写入才会因ENXIO而失败(没有这样的设备或 地址)除非另一端已经打开。
也就是说,您的父/子进程在打开FIFO时会隐式同步。因此,当父进程调用unlink(2)
时,子进程很久以前就打开了FIFO。因此,孩子将始终找到FIFO对象并在父对象上调用unlink(2)
之前将其打开。
关于unlink(2)
的注释:unlink(2)
只是从文件系统中删除文件名;只要至少有一个进程与文件(在这种情况下为FIFO)打开,底层对象将保持不变。只有在该进程终止或关闭文件描述符之后,操作系统才会释放相关资源。 FWIW,这与这个问题的范围无关,但似乎值得注意。
其他一些(无关的)评论:
wait(2)
。它会返回一个错误(你会立即忽略),因为孩子没有分叉任何进程。mkfifo(3)
,fork(2)
,open(2)
,read(2)
,write(2)
,close(2)
和unlink(2)
都可以失败并返回{ {1}}。您应该优雅地处理可能的错误而不是忽略它们。这些玩具程序的常见策略是使用-1
打印描述性错误消息并终止。perror(3)
,以便孩子可以访问它。)