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.