【问题标题】:C++ Linux named pipe hanging on open() with O_WRONLY使用 O_WRONLY 挂在 open() 上的 C++ Linux 命名管道
【发布时间】:2014-07-28 18:40:42
【问题描述】:

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

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("open"); 的错误消息也没有。

我错过了什么?

【问题讨论】:

    标签: c++ linux ipc named-pipes mkfifo


    【解决方案1】:

    当您打开一个 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-在套接字上安排的行为),它等待先前写入的数据被删除。

    【讨论】:

    • 啊,我误以为如果您以只读模式打开程序,程序只会阻塞,直到有写入器。我不知道作家也会等待读者。非常感谢
    • @Kaz 你能解释一下为什么这个条件是必要的吗?
    • @sonukumar:这不是“必要的”;它只是。这就是管道的作用。如果您不想要管道,请使用文件。
    • @LightnessRacesinOrbit 谢谢,但我想知道这背后的一些原因。
    • @sonukumar 我在答案中添加了一段文字,试图解决“为什么”。
    【解决方案2】:

    使用 O_RDWR 而不是 O_WRONLY 进行打开。这将打开 fifo 而不会阻塞,即使另一端尚未打开阅读器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 2019-02-07
      • 2013-07-31
      相关资源
      最近更新 更多