How does the pipe() system call work for anonymous pipes?
pipe() creates an anonymous (unnamed) unidirectional communication channel between related processes.
Prototype:
#include <unistd.h>
int pipe(int pipefd[2]);
pipefd[0] is the read end, pipefd[1] is the write end.
Properties:
- Unidirectional: data flows from
pipefd[1]topipefd[0] - Buffered in the kernel (typically 64KB on Linux)
- FIFO (first-in-first-out) byte stream
- No message boundaries (unlike message queues)
Blocking behavior:
read()on empty pipe blocks until data is available (or all write ends are closed -> returns 0 = EOF)write()on full pipe blocks until space is available (or all read ends are closed ->SIGPIPE)
Typical usage: Create pipe, fork, parent and child each close the end they do not use.
SIGPIPE: If a process writes to a pipe with no readers, SIGPIPE is delivered (default action: terminate). The write returns -1 with errno = EPIPE.
1. pipe(pipefd) -- creates read end [0] and write end [1]
2. fork()
3. Parent: close(pipefd[0]), write to pipefd[1], close(pipefd[1])
4. Child: close(pipefd[1]), read from pipefd[0], close(pipefd[0])
5. read returns 0 when all write ends are closed (EOF)
6. write to pipe with no readers -> SIGPIPE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
int main(void) {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) { perror("fork"); return 1; }
if (pid == 0) {
/* Child: read from pipe */
close(pipefd[1]); /* close unused write end */
char buf[256];
ssize_t n;
while ((n = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
buf[n] = '\0';
printf("Child received: %s", buf);
}
/* n == 0 means parent closed write end (EOF) */
close(pipefd[0]);
_exit(0);
}
/* Parent: write to pipe */
close(pipefd[0]); /* close unused read end */
const char *msgs[] = {"Hello\n", "from\n", "parent\n"};
for (int i = 0; i < 3; i++)
write(pipefd[1], msgs[i], strlen(msgs[i]));
close(pipefd[1]); /* signals EOF to child */
wait(NULL);
return 0;
}
- •pipe() creates pipefd[0] (read) and pipefd[1] (write)
- •Unidirectional byte stream with kernel buffer (~64KB on Linux)
- •Close unused ends after fork to avoid deadlock and to signal EOF
- •read returns 0 (EOF) when all write ends are closed
- •Writing to a pipe with no readers sends SIGPIPE
- •Forgetting to close unused pipe ends causes deadlocks (reader waits forever for EOF)
- •Writes up to PIPE_BUF bytes (typically 4096) are guaranteed atomic
- •Pipes are only between related processes (parent-child via fork)
- •pipe2() on Linux supports O_NONBLOCK and O_CLOEXEC flags