这是我的简单代码,它打开一个命名管道,向其中写入一个字符串,然后关闭该管道。管道是在另一个函数中创建的,如下所述。
char * ipcnm = "./jobqueue";
std::cout << "opening job queue" << std::endl;
//ensure the jobqueue is opened
if ((jobq = open(ipcnm, O_WRONLY)) < 0) {
perror("open");
exit(-1);
}
std::cout << "queue opened" << std::endl;
// record the number of bytes written to the queue
size_t written = write(jobq, ptr, size*nmemb);
// close fifo
if (close(jobq) < 0) {
perror("close");
exit(-1);
}
// need to report to other agents the size of the job that was written
jobSizes.push_back(written);
但是对open()的调用挂起了。我确保在调用时没有其他使用fifo“jobqueue”的进程,并且一旦创建队列,就将队列的文件权限设置为prwxrwxr-x(我只是使用
mkfifo(ipcnm, 0777)
创建管道。起初我以为组
o
缺少此管道上的w
权限是一个问题,所以我用chmod手动更改了它们,但它仍然挂起,因为“queue open”从未打印出来。 perror(“open”)的错误消息也不会;我想念什么?
最佳答案
当您打开用于写入的FIFO时,写入器将被阻塞,直到有读取器为止。
您可能想念读者。
您无法写入管道,然后将其关闭,然后让阅读器随身携带。这样的存储语义是通过使用常规文件来完成的。
管道是一种进程间通信机制。通过打开FIFO创建的管道与pipe
POSIX C库函数返回的对象相似,不同之处在于pipe
返回已经为I/O准备的对象,因为存在两个描述符:两端朝I的相反方向打开/O。 FIFO的端点一次单独打开。
文件系统中的FIFO对象只是一个接触点,它允许多个进程连接到同一管道。
最初,不存在管道对象。当第一个进程在文件系统中的FIFO对象上执行open
时,将创建一个管道。来自同一进程或另一个进程的任何其他open
请求都附加到内核中保存的同一管道对象。只有在打开管道至少一次以进行读取并至少打开一次以进行写入之前,才能进行I/O操作。实际的管道I/O通过内核。它没有存储在文件系统中。当所有进程关闭管道时,对象就会消失。
可以设计一个FIFO,以便在任何进程打开要读取的对象之前就可以开始I/O。也就是说,可以允许继续进行写请求,然后仅在管道填满时才阻塞。该设计将有问题。例如,如果写入量很小,以致管道无法填满怎么办?编写器将写入数据并继续执行。如果只是在读取器读取数据之前退出,则数据将永远消失!阻塞行为可确保读者可以在那里捕获数据。释放写入器后,可以确保读取器已打开管道,因此可以安全关闭管道的末端而不会丢失数据。即使没有可用的读取器,也不能阻止写入的设计必须将管道对象保留在内核内部,即使没有进程打开也是如此,以便写入器可以打开管道,将数据放入其中,然后消失,稍后读者可以提取数据。否则,该设计将不得不向编写者提供一个阻塞的close
(类似于套接字上的SO_LINGER
安排的行为),等待先前写入的数据被删除。
关于C++ Linux命名管道通过O_WRONLY卡在open()上,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24099693/