5

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

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

我错过了什么?

4

2 回答 2

17

When you open a FIFO for writing, the writer is blocked until there is a reader.

You are probably missing the reader.

You cannot write to a pipe, then close it, and then have the reader come along later. Such storage semantics is accomplished by using a regular file.

Pipes are an inter-process communication mechanism; a pipe created by opening a FIFO is similar to the object returned by the pipe POSIX C library function, except that pipe returns an object which is already prepared for I/O, since there are two descriptors: opposite ends open for opposite directions of I/O. Whereas a FIFO's endpoints are separately opened one at a time.

The FIFO object in the filesystem is only a contact point which allows multiple processes to attach to the same pipe.

Initially, no pipe object exists. When the first process executes an open on the FIFO object in the filesystem, a pipe is created. Any additional open requests from the same process or another attach to the same pipe object held in the kernel. I/O cannot take place until the pipe is opened at least once for reading and at least once for writing. The actual pipe I/O goes through the kernel; it is not stored in the filesystem. When all processes close the pipe, the object goes away.

A FIFO could be designed such that I/O can begin before any process has the object open for reading. That is to say, a write request could be allowed to proceed and then block only when the pipe fills up. That design would have issues. For instance, what if the write is small, so that the pipe does not fill up? The writer will write the data and proceed in its execution. If it simply exits before a reader has read the data, the data has disappeared forever! The blocking behavior ensures that a reader is there to catch the data; when the writer is unblocked, it can be sure that a reader has the pipe open, and so it can safely close its end of the pipe without the data being lost. A design which does not block writes even when no reader is available would have to keep the pipe object around inside the kernel even when no process has it open, so that a writer can open a pipe, put data in it, then go away, and later a reader can pick up the data. Or else the design would have to provide, to the writer, a blocking close (similarly to SO_LINGER-arranged behavior on a socket) which waits for previously written data to be removed.

于 2014-06-07T17:18:39.383 回答
2

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

于 2018-03-02T16:32:55.207 回答