FIFO 通道读取不正确

Кир*_*шов 3 c linux named-pipes fifo

我有 2 个不相关的进程。第一个创建一个 FIFO 通道并将数据写入其中。

测试组合:

int main(int argc, char *argv[])
{
    int f1;
    char *send_buf = "Hello";
    char recv_buf[128] = {0};

    if (mkfifo("mk.fifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1 && errno != EEXIST)
        error(0, errno, "mkfifo() error");

    f1 = open("mk.fifo", O_RDWR);
    perror("Opening ");

    printf("Sending string '%s'...\n", send_buf);
    write(f1, send_buf, strlen(send_buf));
    perror("Writing ");

    close(f1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

第二个进程应该从先前创建的通道读取数据。

test2comp:

int main(int argc, char *argv[])
{
    int f2;
    char recv_buf[128] = {0};

    f2 = open("mk.fifo", O_RDONLY|O_NONBLOCK);
    perror("Opening ");

    read(f2, recv_buf, sizeof(recv_buf));
    perror("Reading ");

    printf("Received string '%s'\n", recv_buf);

    close(f2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是读取的数据是空的。可能是什么原因?

控制台输出:

在此处输入图片说明

Use*_*ess 5

FIFO 只是一个命名管道。

它必须是在两端开口的同时以发生的通信。例如,您的本地手册页应该说类似

内核为至少一个进程打开的每个 FIFO 特殊文件维护一个管道对象。FIFO 必须在两端(读和写)都打开,然后才能传递数据。通常,打开 FIFO 会阻塞,直到另一端也打开。

你所做的是:

  1. 创建一个 FIFO inode
  2. 打开它进行写入,隐式创建与该 inode 关联的管道
  3. 将某些内容写入管道缓冲区,即使尚未从中读取任何内容
  4. 再次关闭它,破坏管道
  5. 打开一个新管道进行读取,与相同的(当前未使用的)inode 相关联
  6. 里面什么都没有,因为它是一个新管道

通常我希望作者在打开 fifo 时阻塞,直到有读者出现 - 我不知道为什么没有发生这种情况。您通过将其设置为非阻塞来明确为阅读器禁用此行为。