The Linux Programming Interface

(nextflipdebug5) #1

894 Chapter 44


be sure which process will be the first to succeed—the two processes race for data.
Preventing such races would require the use of some synchronization mechanism.
However, if we require bidirectional communication, there is a simpler way: just
create two pipes, one for sending data in each direction between the two processes.
(If employing this technique, then we need to be wary of deadlocks that may occur
if both processes block while trying to read from empty pipes or while trying to
write to pipes that are already full.)
While it is possible to have multiple processes writing to a pipe, it is typical to
have only a single writer. (We show one example of where it is useful to have multiple
writers to a pipe in Section 44.3.) By contrast, there are situations where it can be useful
to have multiple writers on a FIFO, and we see an example of this in Section 44.8.

Starting with kernel 2.6.27, Linux supports a new, nonstandard system call,
pipe2(). This system call performs the same task as pipe(), but supports an addi-
tional argument, flags, that can be used to modify the behavior of the system
call. Two flags are supported. The O_CLOEXEC flag causes the kernel to enable the
close-on-exec flag (FD_CLOEXEC) for the two new file descriptors. This flag is useful
for the same reasons as the open() O_CLOEXEC flag described in Section 4.3.1. The
O_NONBLOCK flag causes the kernel to mark both underlying open file descriptions
as nonblocking, so that future I/O operations will be nonblocking. This saves
additional calls to fcntl() to achieve the same result.

Pipes allow communication between related processes
In the discussion so far, we have talked about using pipes for communication
between a parent and a child process. However, pipes can be used for communica-
tion between any two (or more) related processes, as long as the pipe was created
by a common ancestor before the series of fork() calls that led to the existence of
the processes. (This is what we meant when we referred to related processes at the
beginning of this chapter.) For example, a pipe could be used for communication
between a process and its grandchild. The first process creates the pipe, and then
forks a child that in turn forks to yield the grandchild. A common scenario is that a
pipe is used for communication between two siblings—their parent creates the pipe,
and then creates the two children. This is what the shell does when building a pipeline.

There is an exception to the statement that pipes can be used to communicate
only between related processes. Passing a file descriptor over a UNIX domain
socket (a technique that we briefly describe in Section 61.13.3) makes it possible
to pass a file descriptor for a pipe to an unrelated process.

Closing unused pipe file descriptors
Closing unused pipe file descriptors is more than a matter of ensuring that a pro-
cess doesn’t exhaust its limited set of file descriptors—it is essential to the correct
use of pipes. We now consider why the unused file descriptors for both the read
and write ends of the pipe must be closed.
The process reading from the pipe closes its write descriptor for the pipe, so
that, when the other process completes its output and closes its write descriptor,
the reader sees end-of-file (once it has read any outstanding data in the pipe).
If the reading process doesn’t close the write end of the pipe, then, after the
other process closes its write descriptor, the reader won’t see end-of-file, even after
Free download pdf