/* pipe.c Jeff Ondich, 15 April 2004 Updated 17 February 2022 Updated 25 February 2026 This program creates two child processes and hooks them up via a pipe, like so: child1 | child2 Then child1 execs "ls" and the child execs "wc -l", so we end up running this pipeline: ls | wc -l Once both child processes have terminated, the parent prints a message and exits. Here's another way to look at it. Parent make a pipe fork child1 fork child2 clean up wait Child1 redirect stdout to pipe clean up exec ls Child2 redirect stdin to pipe clean up exec wc -l */ #include #include #include #include #include #include #include #include int main() { int fd[2]; if (pipe(fd) < 0) { perror("Trouble creating pipe"); exit(1); } printf("Pipe file descriptors: fd[0]=%d, fd[1]=%d\n", fd[0], fd[1]); // create child1 int pid1 = fork(); if (pid1 < 0) { perror("Trouble forking"); exit(1); } if (pid1 == 0) { // child1 printf("Child1 (%d) created\n", getpid()); close(fd[0]); if (dup2(fd[1], STDOUT_FILENO) == -1) { perror("Trouble redirecting stdout"); } close(fd[1]); execlp("ls", "ls", NULL); perror("execlp in child1 failed"); } else { // parent: create child2 int pid2 = fork(); if (pid2 == 0) { // child2 printf("Child2 (%d) created\n", getpid()); close(fd[1]); if (dup2(fd[0], STDIN_FILENO) == -1) { perror("Trouble redirecting stdin"); } close(fd[0]); execlp("wc", "wc", "-l", NULL); perror("execlp in child2 failed"); } else { // parent close(fd[0]); close(fd[1]); int status; int pid = wait(&status); printf("Child (%d) terminated with status %d\n", pid, status); pid = wait(&status); printf("Child (%d) terminated with status %d\n", pid, status); } } return 0; }