Connect2
Code Visualization for pipe()
, fork()
, dup()
The original release is on Ed.
To make it easier to understand the Connect2.c
program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int fd[2];
pid_t pid1, pid2;
// Split arguments ["cmd1", ..., "--", "cmd2", ...] into
// ["cmd1", ...] and ["cmd2", ...]
char **argv1 = argv + 1; // argv for the first command
char **argv2; // argv for the second command
for (argv2 = argv1; *argv2; argv2++) {
if (strcmp(*argv2, "--") == 0) {
*argv2++ = NULL;
break;
}
}
if (*argv1 == NULL || *argv2 == NULL) {
fprintf(stderr, "%s\n", "separate two commands with --");
exit(1);
}
pipe(fd);
if ((pid1 = fork()) == 0) {
close(fd[0]); // Close read end of pipe
dup2(fd[1], 1); // Redirect stdout to write end of pipe
close(fd[1]); // stdout already writes to pipe, close spare fd
execvp(*argv1, argv1);
// Unreachable
}
if ((pid2 = fork()) == 0) {
close(fd[1]); // Close write end of pipe
dup2(fd[0], 0); // Redirect stdin from read end of pipe
close(fd[0]); // stdin already reads from pipe, close spare fd
execvp(*argv2, argv2);
// Unreachable
}
// Parent does not need either end of the pipe
close(fd[0]);
close(fd[1]);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
return 0;
}
I have drawn the following step-by-step code visualization diagram.
Note that for ease of illustration, I have assumed that child processes will take precedence after a fork()
, and have drawn the illustration sequentially.
However, given the concurrent nature of the program, each process (highlighted in different colors) may be running at the same time.
For future OS course teaching teams, please contact me if you need an editable version of the diagram. And feel free to link to this page if you want to share it.