当同一进程使用 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。可能和你有同样的问题。
在单个进程上使用 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。可能和你有同样的问题。