POSIX Pipes Basic creation and usage


Anonymous pipes, or simply pipes, are kernel-managed objects exposed to processes as a pair of file descriptors, one for the read terminus and one for the write terminus. They are created via the pipe(2) function:

int pipefds[2];
int result;

result = pipe(pipefds);

On success, pipe() records the descriptor for the read end of the pipe at index 0 of the provided array, and the descriptor for the write end at index 1; these indices are analogous to the conventional file descriptor numbers for the standard streams.

Having created a pipe, one uses POSIX I/O functions to write to the write end or read from the read end:

Process 1:

ssize_t bytes_written = write(pipefds[1], "Hello, World!", 14);

Process 2:

char buffer[256];
ssize_t bytes_read = read(pipefds[0], buffer, sizeof(buffer));

Alternatively, one can instead use fdopen() to wrap one of both pipe ends in a FILE structure for use with C stdio functions:

FILE *write_end = fdopen(pipefds[1]);

if (write_end) {
    fputs("Hello, World!");

Pipes have finite I/O buffers, and ordinary writes to pipes with full buffers will block. Pipes are therefore not a safe mechanism for a thread to communicate with itself, as if the thread writing to a pipe is also the only one that reads from it, then as soon as a write blocks that thread is deadlocked.

A pipe persists as long as any process has an open file description for either of the pipe ends. The close(2) function can be used to close a pipe end represented by a file descriptor, and fclose(3) can be used to close a pipe end via a FILE wrapped around it.