Step 6: Pipes
A pipe connects two programs: A | B sends A's output into B's input. The shell calls pipe() to get two file descriptors (a read end and a write end), starts both programs with fork, and uses dup2 to hook A's stdout to the write end and B's stdin to the read end. The parent then closes both ends: if it kept the write end open, B would wait forever for more input that never comes.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
// Run "left | right": the left program's output becomes the right program's input.
int run_pipeline(char *left[], char *right[]) {
int fds[2];
if (pipe(fds) != 0) return 1; // fds[0] = read end, fds[1] = write end
fflush(stdout);
pid_t a = fork();
if (a == 0) {
dup2(fds[1], STDOUT_FILENO); // left writes into the pipe
close(fds[0]);
close(fds[1]);
execvp(left[0], left);
_exit(127);
}
pid_t b = fork();
if (b == 0) {
dup2(fds[0], STDIN_FILENO); // right reads from the pipe
close(fds[0]);
close(fds[1]);
execvp(right[0], right);
_exit(127);
}
close(fds[0]); // the parent must close both ends,
close(fds[1]); // or the right program never sees end-of-input
int status;
waitpid(a, &status, 0);
waitpid(b, &status, 0);
return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
}
int main(void) {
char *left1[] = { "echo", "hello pipes", NULL };
char *right1[] = { "tr", "a-z", "A-Z", NULL };
printf("tiny> echo hello pipes | tr a-z A-Z\n");
run_pipeline(left1, right1);
char *left2[] = { "echo", "count these four words", NULL };
char *right2[] = { "wc", "-w", NULL };
printf("tiny> echo count these four words | wc -w\n");
run_pipeline(left2, right2);
return 0;
}tiny> echo hello pipes | tr a-z A-Z HELLO PIPES tiny> echo count these four words | wc -w 4
This is how grep, sort and wc from the Bash course combine into powerful one-liners: each does one job and the pipe joins them. Your shell now does what the shell on your computer does.
Why must the parent close its copies of the pipe ends?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.