繁体   English   中英

C ++ Linux命名管道挂在open()上,带有O_WRONLY

[英]C++ Linux named pipe hanging on open() with O_WRONLY

这是我的简单代码,它打开命名管道,将字符串写入其中,然后关闭管道。 管道是在另一个功能中创建的,如下所述。

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,它仍然挂起,为“队列打开”永远不会被打印出来。 perror的错误消息也没有(“打开”);

我错过了什么?

当您打开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 -arranged行为),它等待先前写入的数据被删除。

使用O_RDWR代替O_WRONLY进行打开。 这将打开fifo而不阻塞,即使读者没有打开另一端。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM