系统相关
首页 > 系统相关> > C Linux命名管道挂在open()上,带有O_WRONLY

C Linux命名管道挂在open()上,带有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缺少对此管道的权限,所以我用chmod手动更改它们并且它仍然挂起,因为“队列打开”永远不会被打印. perror的错误消息也没有(“打开”);

我错过了什么?

解决方法:

当您打开FIFO进行写入时,编写器将被阻止,直到有读取器为止.

你可能错过了读者.

你不能写入管道,然后关闭它,然后让读者稍后出现.这种存储语义是通过使用常规文件来完成的.

管道是一种进程间通信机制;通过打开FIFO创建的管道类似于管道POSIX C库函数返回的对象,除了管道返回已经为I / O准备的对象,因为有两个描述符:对于I的相反方向打开的相对端/ O.而FIFO的端点是一次一个地单独打开的.

文件系统中的FIFO对象只是一个允许多个进程连接到同一管道的联系点.

最初,不存在管道对象.当第一个进程在文件系统中的FIFO对象上执行open时,将创建一个管道.来自同一进程的任何其他打开请求或另一个附加到内核中保存的同一管道对象.在管道至少打开一次以进行读取之前不能进行I / O,至少一次用于写入.实际的管道I / O通过内核;它不存储在文件系统中.当所有进程关闭管道时,对象就会消失.

可以设计FIFO,使得I / O可以在任何进程打开对象以进行读取之前开始.也就是说,可以允许写入请求继续,然后仅在管道填满时阻止.那个设计会有问题.例如,如果写入很小,管道不会填满怎么办?编写器将编写数据并继续执行.如果它只是在读者读取数据之前退出,数据就会永远消失!阻塞行为确保读者可以捕获数据;当编写器被解锁时,可以确定读取器已打开管道,因此它可以安全地关闭管道末端而不会丢失数据.即使没有可用的读取器,也不会阻止写入的设计必须将管道对象保持在内核内部,即使没有进程打开它,这样作者可以打开管道,将数据放入其中,然后离开,后来读者可以拿起数据.否则,设计必须向编写器提供阻塞关闭(类似于套接字上的SO_LINGER排列的行为),其等待先前写入的数据被移除.

标签:c-2,linux,ipc,named-pipes,mkfifo
来源: https://codeday.me/bug/20190713/1454139.html