wanttobepro
wanttobepro

Reputation: 43

exec() and pipe() between child process in C

I'm trying to implement this using pipe() and fork() :

ls | wc

First I checked if pipe works fine, and here is the code.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

int main(void){

    char *param1[]={"ls",NULL};
    char *param2[]={"wc",NULL};

    int p[2];
    pipe(p);

    pid_t process1, process2;

    if((process1=fork())==0){ // child 1
        dup2(p[1],1); // redirect stdout to pipe
        close(p[0]);
        execvp("ls", param1);
        perror("execvp ls failed");
    }
    else if(process1>0){ // parent
        wait(NULL);
    }

    if((process2=fork())==0){ // child 2
        dup2(p[0],0); // get stdin from pipe
        close(p[1]);

        char buff[1000]={0};
        read(STDIN_FILENO,buff,250);
        printf("---- in process2 -----\n%s\n",buff);
    }
    else if(process2>0){ // parent
        wait(NULL);
    }
    return 0;
}

I checked it works fine. I replaced read() and printf() to exec(), like :

if((process2=fork())==0){ // child 2
    dup2(p[0],0); // get stdin from pipe
    close(p[1]);

    execvp("wc",param2);
    perror("execvp wc failed");
}

My terminal just hang. I think wc process doesn't get any input. So my question is, why read() and printf() works, and execvp() doesn't work?

Upvotes: 4

Views: 6109

Answers (1)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

You need not to wait every time you create a new process and also close the descriptor in the parent, something like:

if((process1=fork())==0){ // child 1
    dup2(p[1],1); // redirect stdout to pipe
    close(p[0]);
    execvp("ls", param1);
    perror("execvp ls failed");
}
else if(process1==-1){ // fork failed
    exit(1);
}
close(p[1]); // no need for writing in the parent

if((process2=fork())==0){ // child 2
    dup2(p[0],0); // get stdin from pipe

    char buff[1000]={0};
    read(STDIN_FILENO,buff,250);
    printf("---- in process2 -----\n%s\n",buff);
}
else if(process2==-1){ // second fork failed
    close(p[0]); // ensure there is no reader to the pipe
    wait(NULL); // wait for first chidren
    exit(1);
}
close(p[0]); // no need for reading in the parent

wait(NULL);
wait(NULL); // wait for the two children

Upvotes: 1

Related Questions