unlink()之后从FIFO读取 [英] Reading from FIFO after unlink()

查看:347
本文介绍了unlink()之后从FIFO读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个FIFO,将其写入并取消链接. 令我惊讶的是,取消链接后我能够从fifo读取数据,为什么?

I have created a FIFO, wrote to it and unlinked it. To my surprise I was able to read data from the fifo after unlinking, why is that?

#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;
}

推荐答案

除非将O_NONBLOCK标志传递给open(2),否则将打开FIFO块,直到另一端打开为止.来自man 7 fifo:

Unless you pass the O_NONBLOCK flag to open(2), opening a FIFO blocks until the other end is opened. From man 7 fifo:

在数据发送之前,必须在两端打开FIFO(读取和写入) 可以通过.通常,打开FIFO块直到另一端 也打开了.

The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.

一个进程可以在非阻塞模式下打开FIFO.在这种情况下,打开 即使在写侧没有人打开,只读也将成功 但是,ENXIO只能打开只写操作(没有这样的设备或 地址),除非另一端已经打开.

A process can open a FIFO in nonblocking mode. In this case, opening for read only will succeed even if no-one has opened on the write side yet, opening for write only will fail with ENXIO (no such device or address) unless the other end has already been opened.

这意味着,您的父/子进程在打开FIFO时隐式同步.因此,当父进程调用unlink(2)时,子进程很早就打开了FIFO.因此,子代将始终 找到FIFO对象,并在父代对其调用unlink(2)之前将其打开.

Which is to say, your parent / child processes are implicitly synchronized upon opening the FIFO. So by the time the parent process calls unlink(2), the child process opened the FIFO long ago. So the child will always find the FIFO object and open it before the parent calls unlink(2) on it.

关于unlink(2)的注释:unlink(2)只是从文件系统中删除文件名.只要至少有一个进程打开了文件(在这种情况下为FIFO),底层对象就会保留下来.只有在该过程终止或关闭文件描述符之后,操作系统才会释放关联的资源. FWIW,这与这个问题的范围无关,但似乎值得注意.

A note about unlink(2): unlink(2) simply deletes the filename from the filesystem; as long as there is at least one process with the file (FIFO in this case) open, the underlying object will persist. Only after that process terminates or closes the file descriptor will the operating system free the associated resources. FWIW, this is irrelevant in the scope of this question, but it seems worth noting.

其他一些(不相关的)备注:

A couple of other (unrelated) remarks:

  • 不要在孩子身上呼叫wait(2).它将返回一个错误(您将立即忽略),因为子级没有派生任何进程.
  • mkfifo(3)fork(2)open(2)read(2)write(2)close(2)unlink(2)都可能失败并返回-1.您应该优雅地处理可能的错误,而不是忽略它们.这些玩具程序的常见策略是使用perror(3)打印描述性错误消息并终止.
  • 如果只希望父级与子级之间的通信,请使用管道:它更易于设置,不需要取消链接,并且它不会在文件系统中公开(但是您需要先使用pipe(2)创建它分叉,以便孩子可以访问它.)
  • Don't call wait(2) on the child. It will return an error (which you promptly ignore), because the child didn't fork any process.
  • mkfifo(3), fork(2), open(2), read(2), write(2), close(2) and unlink(2) can all fail and return -1. You should gracefully handle possible errors instead of ignoring them. A common strategy for these toy programs is to print a descriptive error message with perror(3) and terminate.
  • If you just want parent to child communication, use a pipe: it's easier to setup, you don't need to unlink it, and it is not exposed in the filesystem (but you need to create it with pipe(2) before forking, so that the child can access it).

这篇关于unlink()之后从FIFO读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆