同一进程使用FIFO两端时无法重新打开FIFO

Posted

技术标签:

【中文标题】同一进程使用FIFO两端时无法重新打开FIFO【英文标题】:Cannot reopen FIFO when the same process uses both ends of the FIFO 【发布时间】:2016-12-17 01:02:45 【问题描述】:

在单个进程上使用 FIFO 时,看起来在两端都打开并关闭之后,不可能重用 FIFO。任何重新打开封闭端的尝试都失败或返回的文件描述符无用。

是否可以解决此问题,或者我们是否必须保持 FIFO 的两端都打开,直到我们完全确定不再需要它?

以下是一些测试代码,显示并尝试重新打开 FIFO 的封闭写入端:

#include <iostream>
#include <cstdio>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

using namespace std;

int main(int argc, const char **argv)

      cout << "Creating an instance of a named pipe..." << endl;
      mode_t prevMask = umask(0);
      if (mknod("my_pipe", S_IFIFO | 0666, 0))
         return -1;
      umask(prevMask);

      cout << "Opening Read end..." << endl;
      int fdM = open("my_pipe", O_RDONLY | O_NONBLOCK);
      if (fdM == -1)
         return -1;

      cout << "Opening Write end..." << endl;
      int fdS = open("my_pipe", O_WRONLY | O_NONBLOCK);
      if (fdS == -1)
         return -1;

      cout << "Sending data to pipe..." << endl;
      const char *data = "Hello my friend!";
      ssize_t NbOfBytesWritten = write(fdS, data, strlen(data));
      if (NbOfBytesWritten < 0)
         return -1;
      cout << "Number of bytes sent: " << NbOfBytesWritten << endl;

      cout << "Closing Write end..." << endl;
      if (close(fdS))
         return -1;

      cout << "Reopening Write end..." << endl;
      fdS = open("my_pipe", O_WRONLY | O_NONBLOCK);
      if (fdS == -1)
      
         cout << "open() - failed("<< errno << "): " << strerror(errno) << '.';
         remove("my_pipe");
         return -1;
      

      cout << "Sending some more data to pipe..." << endl;
      data = "What's up?";
      NbOfBytesWritten = write(fdS, data, strlen(data));
      if (NbOfBytesWritten < 0)
         return -1;
      cout << "Number of bytes sent: " << NbOfBytesWritten << endl;

      cout << "Reading data from pipe..." << endl;
      char buff[128];
      ssize_t numBytesRead = read(fdM, buff, 127);
      if (NbOfBytesWritten < 0)
         return -1;
      buff[numBytesRead] = '\0'; // null terminate the string
      cout << "Number of bytes read: " << numBytesRead << endl;
      cout << "Message: " << buff << endl;

      cout << "Closing Write end..." << endl;
      if (close(fdS))
         return -1;

      cout << "Closing Read end..." << endl;
      if (close(fdM))
         return -1;

      cout << "Deleting pipe..." << endl;
      if (remove("my_pipe"))
         return -1;

   return 0;

这是输出:

Creating an instance of a named pipe...
Opening Read end...
Opening Write end...
Sending data to pipe...
Number of bytes sent: 16
Closing Write end...
Reopening Write end...
open() - failed(6): No such device or address.

我还测试了类似的代码,试图重新打开一个封闭的读取端(而写入端保持打开)。在这种情况下,open() 函数成功,但使用 open() 返回的文件描述符的 read() 函数失败,并显示: 发送时发生通信错误。 (70)

编辑:

我正在使用 CYGWIN。

【问题讨论】:

这在我的 Linux 上运行没有错误。 你需要保持两端打开。当所有写端都关闭时,读取器将获得 EOF。当所有读取端都关闭时,如果作者尝试写入,则会收到EPIPE @Barmar - 问题是:“为什么不能重新打开 FIFO 的末端?”这与写入或读取两端未连接的 FIFO 的效果无关。 其实我收回了。我认为您可以重新打开写入端。我刚刚做了一个测试,我在一个终端上运行了sleep 500 &lt; /tmp/fifo。然后在另一个终端我做了echo foo &gt; /tmp/fifo; echo bar &gt; /tmp/fifo 您的输出与程序不匹配。 Reading data from pipe... 消息在哪里? 【参考方案1】:

您的代码在 Linux 上运行良好。我认为您遇到的问题是 CYGWIN 上的命名管道不能很好地工作并且无法遵循 POSIX 语义。见FIFO (named pipe) is broken on Cygwin。可能与您遇到的问题相同。

【讨论】:

以上是关于同一进程使用FIFO两端时无法重新打开FIFO的主要内容,如果未能解决你的问题,请参考以下文章

无法打开FIFO

如果我在同一个程序中打开一个 FIFO 进行读写会发生啥?

FIFO调用open时阻塞

[Linux进程间通信]FIFO

在 FIFO 到达时从 FIFO 中读取数据(linux)

mkfifo 替代品