The code shown is practically for work (it cuts several angles, but it works), because the branched children guarantee that the file descriptor of the executed process will write (in the case of ls ) and read from (in the case of wc ) - the corresponding end of the pipe . You no longer have to do; the standard input is file descriptor 0, so wc with no (filename) arguments is read from standard input. ls always writes to standard output, file descriptor 1, if it does not write an error message.
There are three processes in the code snippet; parent process and two children, one from each fork() . The parent process should also cover both ends of the pipe; he closes only one.
In general, after calling dup() or dup2() in the pipe file descriptor, you must close both ends of the pipe. You leave here because ls generates data and exits; you would not be under any circumstances.
A comment:
is inaccurate; you set stdout to the output side of the channel, not to the input side.
After execv() calls, you should have an error output; if they fail, they return, and the process can lead to chaos (for example, if ls fails, you get two copies of wc .
Pay attention to carefully closing both ends of the pipe in each of the processes. The parent process is not used for the channel once it has launched both children. I left the code that closes filedes[1] at an early stage (but removed it from the explicit else block, since the following code was also executed only if else was executed). I could store closes() pairs in each of the three code paths where the files should be closed.
#include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> int main(void) { int filedes[2]; int corpse; int status; pipe(filedes); /* Run LS. */ pid_t pid = fork(); if (pid == 0) { /* Set stdout to the output side of the pipe, and run 'ls'. */ dup2(filedes[1], 1); close(filedes[1]); close(filedes[0]); char *argv[] = {"ls", NULL}; execv("/bin/ls", argv); fprintf(stderr, "Failed to execute /bin/ls\n"); exit(1); } /* Close the input side of the pipe, to prevent it staying open. */ close(filedes[1]); /* Run WC. */ pid = fork(); if (pid == 0) { /* Set stdin to the input side of the pipe, and run 'wc'. */ dup2(filedes[0], 0); close(filedes[0]); char *argv[] = {"wc", NULL}; execv("/usr/bin/wc", argv); fprintf(stderr, "Failed to execute /usr/bin/wc\n"); exit(1); } close(filedes[0]); while ((corpse = waitpid(-1, &status, 0)) > 0) printf("PID %d died 0x%.4X\n", corpse, status); return(0); }
Output Example:
$ ./pipes-14312939 32 32 389 PID 75954 died 0x0000 PID 75955 died 0x0000 $