Autumn 2021
Jerry Cain
PDF
int pipe(int fds[]);
int dup2(int source, int target);
int dup(int source);
poohbear@myth51:~$ cat /usr/include/tar.h | wc
112 600 3786
poohbear@myth51:~$ echo -e "pear\ngrape\npeach\napricot\nbanana\napple" | sort | grep ap
apple
apricot
grape
poohbear@myth51:~$ time sleep 5 | sleep 10
real 0m10.004s
user 0m0.006s
sys 0m0.001s
poohbear@myth55:~$ curl -sL "http://cs110.stanford.edu/odyssey.txt" | sed 's/[^a-zA-Z ]/ /g' |
> tr 'A-Z ' 'a-z\n' | grep [a-z] | sort -u |
> comm -23 - <(sort /usr/share/dict/words) | less
poohbear@myth55:~$
pipeline
function that codes to the following interface:pipeline
accepts two argument vectors and, assuming both vectors are valid, spawns off twin processes with the added bonus that the standard output of the first is directed to the standard input of the second.
pipeline
calls are well-formed and work as expected. argv1
and argv2
are each valid, NULL
-terminated argument vectors, and pids
is the base address of an array of length two.pipe
, dup2
, close
, execvp
, and so forth succeed so that you needn't do any error checking whatsoever.pipeline
should return without waiting for either of the child processes to finish, and the pids of the two processes are dropped into pids[0]
and pids[1]
.void pipeline(char *argv1[], char *argv2[], pid_t pids[]);
pid_t pids[2];
pipeline({"sleep", "10", NULL}, {"sleep", "10", NULL}, pids);
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe(fds);
pids[0] = fork();
if (pids[0] == 0) {
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(argv1[0], argv1);
}
close(fds[1]); // was only relevant to first child, so close before second fork
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
void pipeline(char *argv1[], char *argv2[], pid_t pids[]) {
int fds[2];
pipe2(fds, O_CLOEXEC);
pids[0] = fork();
if (pids[0] == 0) {
dup2(fds[1], STDOUT_FILENO);
execvp(argv1[0], argv1);
}
close(fds[1]);
pids[1] = fork();
if (pids[1] == 0) {
dup2(fds[0], STDIN_FILENO);
execvp(argv2[0], argv2);
}
close(fds[0]);
}
int pipe2(int fds[], int flags);
From the command line
# Pause PID 1234
myth61$ kill -STOP 1234
# Resume PID 1234
myth61$ kill -CONT 1234
Programmatically
// Pause PID 1234
kill(1234, SIGSTOP);
// Resume PID 1234
kill(1234, SIGCONT);
pid_t pid = waitpid(-1, &status, WUNTRACED);
pid_t pid = waitpid(-1, &status, WCONTINUED);
pid_t pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);