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

Cannot reopen FIFO when the same process uses both ends of the FIFO

在单个进程上使用 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] = '[=10=]'; // 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 上运行良好。我认为您 运行 遇到的问题是 CYGWIN 上的命名管道不能很好地工作并且无法遵循 POSIX 语义。参见 FIFO (named pipe) is broken on Cygwin。可能和你有同样的问题。