System Interface Guide

Pipes

A pipe between two processes is a pair of files that is created in a parent process. It connects the resulting processes when the parent process forks. A pipe has no existence in any file name space, so it is said to be anonymous. It is most common for a pipe to connect only two processes, although any number of child processes can be connected to each other and their parent by a single pipe.

A pipe is created in the process that becomes the parent by a call to pipe(2). The call returns two file descriptor in the array passed to it. After forking, both processes use p[0] to read from and p[1] to write to. The processes actually read from and write to a circular buffer that is managed for them.

Since on a fork(2) the per-process open file table is duplicated, each process has two readers and two writers. The extra readers and writers must be closed if the pipe is to function properly. For example, no end-of-file indication would ever be returned if the other end of a reader is also open for writing by the same process. The following code shows pipe creation, a fork, and clearing the duplicate pipe ends.


#include <stdio.h>
#include <unistd.h>
 ...
 	int p[2];
 ...
 	if (pipe(p) == -1) exit(1);
 	switch( fork() )
 	{
 		case 0:						/* in child */
 			close( p[0] );
 			dup2( p[1], 1);
 			close P[1] );
 			exec( ... );
 			exit(1);
 		default:						/* in parent */
 			close( p[1] );
 			dup2( P[0], 0 );
 			close( p[0] );
 			break;
 	}
 	...

Table 7-1 shows the results of reads from and writes to a pipe under certain conditions.

Table 7-1 Read/write results in a pipe

Attempt 

Conditions 

Result 

read 

Empty pipe, writer attached 

Read blocked 

write 

Full pipe, reader attached 

Write blocked 

read 

Empty pipe, no writer attached 

EOF returned 

write 

No reader 

SIGPIPE

Blocking can be prevented by calling fcntl(2) on the descriptor to set FNDELAY. This causes an error return (-1) from the I/O call with errno set to EWOULDBLOCK.