pipe() and fork() in c -


i need create 2 child processes. 1 child needs run command "ls -al" , redirect output input of next child process, in turn run command "sort -r -n -k 5" on input data. finally, parent process needs read (data sorted) , display in terminal. final result in terminal (when executing program) should same if entered following command directly in shell: "ls -al | sort -r -n -k 5". need use following methods: pipe(), fork(), execlp().

my program compiles, don't desired output terminal. don't know wrong. here code:

#include <sys/types.h> #include <stdio.h> #include <string.h> #include <unistd.h>  int main() {     int fd[2];     pid_t ls_pid, sort_pid;     char buff[1000];      /* create pipe */     if (pipe(fd) == -1) {         fprintf(stderr, "pipe failed");         return 1;     }      /* create child 2 first */     sort_pid = fork();     if (sort_pid < 0) {                         // error creating child 2 process         fprintf(stderr, "\nchild 2 fork failed");         return 1;     }     else if(sort_pid > 0) {                     // parent process          wait(null);                             // wait children termination          /* create child 1 */         ls_pid = fork();         if (ls_pid < 0) {                       // error creating child 1 process             fprintf(stderr, "\nchild 1 fork failed");             return 1;         }         else if (ls_pid == 0) {                 // child 1 process             close(1);                           // close stdout             dup2(fd[1], 1);                     // make stdout same fd[1]             close(fd[0]);                       // don't need end of pipe             execlp("bin/ls", "ls", "-al", null);// executes ls command         }          wait(null);         read(fd[0], buff, 1000);                // parent reads data          printf(buff);                           // parent prints data terminal        }     else if (sort_pid == 0) {                   // child 2 process         close(0);                               // close stdin         dup2(fd[0], 0);                         // make stdin same fd[0]         close(fd[1]);                           // don't need end of pipe         execlp("bin/sort", "sort", "-r", "-n", "-k", "5", null); // executes sort operation     }      return 0; } 

your parent process waits sort process finish before creating ls process.

the sort process needs read input before can finish. , input coming ls won't started until after wait. deadlock.

you need create both processes, wait both of them.

also, file descriptor manipulations aren't quite right. in pair of calls:

close(0); dup2(fd[0], 0); 

the close redundant, since dup2 automatically close existing fd 0 if there one. should close(fd[0]) after ther dup2, have 1 file descriptor tied end of pipe. , if want robust, should test wither fd[0]==0 already, , in case skip dup2 , close.

apply of other dup2 also.

then there's issue of parent process holding pipe open. i'd should close both ends of pipe in parent after you've passed them on children, have weird read fd[0] after last wait... i'm not sure why that's there. if ls|sort pipeline has run correctly, pipe empty afterward, there nothing read. in case, need close fd[1] in parent, otherwise sort process won't finish because pipe won't indicate eof until writers closed.

after weird read printf crash, since read buffer won't '\0'-terminated.

and point of using execlp $path lookup don't have specify /bin/. first test run failed because sort in /usr/bin/. why hardcode paths when don't have to?


Comments