unlink()后从FIFO读取

时间:2015-08-29 14:23:30

标签: c ipc fifo

我创建了一个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;
}

1 个答案:

答案 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),以便孩子可以访问它。)