I've been trying to implement the following command in c: cat /etc/passwd | cut –f1 –d: | sort
This is the code I've got so far. The first pipe works correctly but the second pipe doesn't seem to work at all.
I've checked the code over and over but can't see anything wrong. Can anyone provide a suggestion that will fix my problem?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pipe(pipe_A);
pipe(pipe_B);
pid_t pid_A, pid_B, pid_C;
if( !(pid_A = fork()) ) {
close(1); /* close normal stdout */
dup(pipe_A[1]); /* make stdout same as pipe_A[1] */
close(pipe_A[0]); /* we don't need this */
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
if( !(pid_B = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_A[0]); /* make stdin same as pipe_A[0] */
close(pipe_A[1]); /* we don't need this */
close(1); /* close normal stdout */
dup(pipe_B[1]); /* make stdout same as pipe_B[1] */
close(pipe_B[0]); /* we don't need this */
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
if( !(pid_C = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_B[0]); /* make stdin same as pipe_B[0] */
close(pipe_B[1]); /* we don't need this */
execlp("/usr/bin/sort", "sort", NULL);
}
return 0;
}
Thank you.
The problem is that you are leaking open FDs all around. Note that every time you call fork all the open pipes are inherited by the child process, but pipes with dup'ed FDs don't work properly.
For example, cat
is inheriting both read and write FDs of pipe_B
. Likewise, sort
is inheriting both FDs of pipe_A
.
The right way to go would be along the lines of (but I recommend to use dup2()
instead):
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pid_t pid_A, pid_B, pid_C;
pipe(pipe_A);
if( !(pid_A = fork()) ) {
close(pipe_A[0]); // A-read not needed here
close(1);
dup(pipe_A[1]);
close(pipe_A[1]); //do not pass A-write twice
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
close(pipe_A[1]); // A-write not needed anymore
pipe(pipe_B); //do not create this pipe until needed
if( !(pid_B = fork()) ) {
close(pipe_B[0]); // B-read not needed here
close(0);
dup(pipe_A[0]);
close(pipe_A[0]); //do not pass A-read twice
close(1);
dup(pipe_B[1]);
close(pipe_B[1]); //do not pass B-write twice
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
close(pipe_A[0]); // A-read not needed anymore
close(pipe_B[1]); // B-write not needed anymore
if( !(pid_C = fork()) ) {
close(0);
dup(pipe_B[0]);
close(pipe_B[0]); // do not pass B-read twice
execlp("/usr/bin/sort", "sort", NULL);
}
close(pipe_B[0]); // B-read not needed anymore
return 0;
}
If you analyze my code (and if I wrote it right), assuming that the parent process has only FDs 0, 1 and 2, every single execlp()
will get exactly 3 FDs, 0, 1 and 2.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.