C program to perform a pipe on three commands

2019-05-26 05:04发布

问题:

I have to write a program that will perform the same operation that du | sort | head in the command line would do, but I'm stuck, and my program is not working. The output right now is 112 . and the program doesn't terminate. Please help, I don't know what to do!

int main(void) {

int fd[2];
int fd1[2];
int pid;

if (pipe(fd) == -1) {
    perror("Pipe");
    exit(1);
}

switch (fork()) {
 case -1:
    perror("Fork");
    exit(2);
 case 0:            
    dup2(fd[1], STDOUT_FILENO);
    close(fd[0]);
    close(fd[1]);
    execl("/usr/bin/du", "du", (char *) 0);
    exit(3);
}
if (pipe(fd1) == -1) {
    perror("Pipe");
    exit(1);
} 

switch (fork()) {
 case -1:
    perror("Fork");
    exit(2);
 case 0:    
    dup2(fd[0], STDIN_FILENO);
    dup2(fd1[1], STDOUT_FILENO);
    close(fd[0]);
    close(fd[1]);
    close(fd1[0]);
    close(fd1[1]);
    execl("/usr/bin/sort", "sort", (char *) 0);
    exit(3);
}

close(fd[0]);
close(fd[1]);

switch (fork()) {
 case -1:
    perror("Fork");
    exit(2);
 case 0:    
    dup2(fd1[0], STDIN_FILENO);
    close(fd1[0]);
    close(fd1[1]);
    execl("/usr/bin/head", "head", (char *) 0);
    exit(3);
}

}

回答1:

Let head be your parent process, sort — its child process, and du — the child of sort, or the grandchild of head.

You need two pipes, thus, two arrays — fd and fd1. Let the fd pipe connect sort with head, and fd1 — du with sort.

You will need one big switch statement, which will determine whether you currently are in the parent process (head, pipe(fd) is not 0) or the child (sort, pipe(fd) is 0). If you are in sort, you need to create the fd1 pipe and run the grandchild process du. Now, since you again have two processes (three in total), you need to set a pipe according to your location — whether you are in the grandchild or the child process. You can use a similar switch statement as you did for pipe fd. The trick here is to set the input and output for fd1 pipe correctly.

Your code must do something like this:

int main(void) {

    int fd[2];             // sort <===> head
    int fd1[2];            //  du  <===> sort

    pipe(fd);

    switch (fork()) {
        case 0:            // Are we in sort?
             pipe(fd1);    // If yes, let's make a new pipe!

             switch (fork()) {
                 case 0:   // Are we in du?
                     dup2(fd1[1], STDOUT_FILENO);
                     close(fd1[0]);
                     close(fd1[1]);
                     execl("/usr/bin/du", "du", (whatever directory), NULL);
                     exit(1);

                 default:
                     /* If not in du, we're in sort! in the middle!
                        Let's set up both input and output properly.
                        We have to deal with both pipes */
                     dup2(fd1[0], STDIN_FILENO);
                     dup2(fd[1], STDOUT_FILENO);
                     close(fd1[0]);
                     close(fd1[1]);
                     execl("/usr/bin/sort", "sort (flags if needed)", (char *) 0);
                     exit(2);
             }

            exit(3);

        default:            // If we're not in sort, we're in head
            dup2(fd[0], STDIN_FILENO);
            close(fd[0]);
            close(fd[1]);
            execl("/usr/bin/head", "head (flags if needed)", (char *) 0);
            exit(4);

    }   
}