同一进程使用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 < /tmp/fifo
。然后在另一个终端我做了echo foo > /tmp/fifo; echo bar > /tmp/fifo
。
您的输出与程序不匹配。 Reading data from pipe...
消息在哪里?
【参考方案1】:
您的代码在 Linux 上运行良好。我认为您遇到的问题是 CYGWIN 上的命名管道不能很好地工作并且无法遵循 POSIX 语义。见FIFO (named pipe) is broken on Cygwin。可能与您遇到的问题相同。
【讨论】:
以上是关于同一进程使用FIFO两端时无法重新打开FIFO的主要内容,如果未能解决你的问题,请参考以下文章