pipe(2)
System call
Creates a one-way channel in the kernel and returns two descriptors, one for reading and one for writing. Combined with fork, it connects two processes.
#include <unistd.h>
int pipe(int pipefd[2]);Description
pipe creates a one-way communication channel and fills the array you pass it with two file descriptors: pipefd[0] is the read end, pipefd[1] the write end. What you write into pipefd[1] with write comes out of pipefd[0] with read, in the same order. In between, the data waits in a kernel buffer (16 pages on Linux, so 65,536 bytes with 4 KiB pages).
On its own, a pipe is not much use. Created before a fork, it is inherited by the child, and both processes then hold both ends of the same pipe. One writes, the other reads, and each one closes the end it does not use. That is the mechanism behind the shell's |, with dup2 to plug the pipe into standard input or standard output.
Return value
0 on success. -1 on error, with errno (EMFILE when the process has reached its limit of open descriptors, ENFILE for the system-wide limit); the array is then left unchanged.
Pitfalls
readreturns 0, the end of the stream, only once every write end is closed, in every process. Apipefd[1]left open by mistake in the parent is enough to block the reader forever.Writing to a pipe whose read end nobody holds anymore sends the
SIGPIPEsignal, which terminates the process by default.A full pipe blocks
writeuntil the reader consumes some data. Two processes that write to each other without reading can block each other.Both ends are ordinary descriptors: remember to close them like any file.
Example
#include <stdio.h>#include <sys/wait.h>#include <unistd.h>
int main(void){ int fd[2]; char buf[64]; ssize_t n;
if (pipe(fd) == -1) { perror("pipe"); return 1; } if (fork() == 0) { close(fd[1]); while ((n = read(fd[0], buf, sizeof buf)) > 0) write(STDOUT_FILENO, buf, n); close(fd[0]); return 0; } close(fd[0]); write(fd[1], "hello from parent\n", 18); close(fd[1]); wait(NULL); return 0;}$ gcc -Wall -Wextra pipe.c -o pipe$ ./pipehello from parentThe child closes the write end and reads until the end of the stream; the parent closes the read end, writes, then closes the write end. That last close is what lets the child's loop finish.
pipe_chain
Write pipe_chain, which puts a pipe between each pair of commands in a list and closes every end a process no longer needs.