Autumn 2021
Jerry Cain
PDF
int pipe(int fds[]);
pipe
system call.
pipe
system call takes an uninitialized array of two integers—we'll call it fds
—and populates it with two file descriptors such that everything written to fds[1]
can be read from fds[0]
.pipe
is particularly useful for allowing parent processes to communicate with spawned child processes.
Illustration courtesy of Roz Cyrus.
Illustration by Roz.
myth58$ echo -e "peach\npear\napple" | sort | grep ea
Illustration by Roz.
int main(int argc, char *argv[]) {
int fds[2];
pipe(fds);
pid_t pid = fork();
if (pid == 0) {
close(fds[1]);
char buffer[6];
read(fds[0], buffer, sizeof(buffer)); // assume one call is enough
printf("Read from pipe bridging processes: %s.\n", buffer);
close(fds[0]);
return 0;
}
close(fds[0]);
write(fds[1], "hello", 6);
close(fds[1]);
waitpid(pid, NULL, 0);
return 0;
}
Illustration by Roz.
Illustration by Roz.
Illustration by Roz.
Illustration by Roz.
int dup2(int source, int target);
dup2(fds[0], STDIN_FILENO); // STDIN_FILENO is a #define constant for 0
close(fds[0]);
typedef struct {
pid_t pid;
int supplyfd;
} subprocess_t;
subprocess_t subprocess(char *command);
int main(int argc, char *argv[]) {
subprocess_t sp = subprocess("/usr/bin/sort");
const char *words[] = {
"felicity", "umbrage", "susurration", "halcyon",
"pulchritude", "ablution", "somnolent", "indefatigable"
};
for (size_t i = 0; i < sizeof(words)/sizeof(words[0]); i++) {
dprintf(sp.supplyfd, "%s\n", words[i]);
}
close(sp.supplyfd); // necessary to trigger end-of-input within child
waitpid(sp.pid, NULL, 0);
return 0;
}
poohbear@myth60$ ./subprocess
ablution
felicity
halcyon
indefatigable
pulchritude
somnolent
susurration
umbrage
poohbear@myth60$
poohbear@myth60$ ./subprocess
ablution
felicity
halcyon
indefatigable
pulchritude
somnolent
susurration
umbrage
poohbear@myth60$
int main(int argc, char *argv[]) {
subprocess_t sp = subprocess("/usr/bin/sort");
const char *words[] = {
"felicity", "umbrage", "susurration", "halcyon",
"pulchritude", "ablution", "somnolent", "indefatigable"
};
for (size_t i = 0; i < sizeof(words)/sizeof(words[0]); i++) {
dprintf(sp.supplyfd, "%s\n", words[i]);
}
close(sp.supplyfd); // necessary to trigger end-of-input within child
waitpid(sp.pid, NULL, 0);
return 0;
}
subprocess_t subprocess(char *command) {
int fds[2];
pipe(fds);
subprocess_t process = { fork(), fds[1] };
if (process.pid == 0) {
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
char *argv[] = {"/bin/sh", "-c", command, NULL};
execvp(argv[0], argv);
}
close(fds[0]);
return process;
}