1
votes

I'm relatively new to piping and forking in C,

I have a parent and a child process and try to communication between them.

I created a pipe such that: stdout of parent will connect to stdin of child, and stdout of child will connect to stdin of parent.

I test this by trying to make parent sent out "A" through its stdout and then child will receive "A" from its stdin, after that it should send back "B" from its stdout to parent's stdin.

Here is my code,

bool pget_input(void){
    char buffer[80];
    fprintf(stdout,"A");
    fprintf(stderr,"Parent sent out 'A' to child \n");
    do{
        if (!fgets(buffer, 20, stdin)) {
            fprintf(stderr,"Parent failed to recieve from child\n");
            return false;                                        
        }
        fprintf(stderr,"Parent receiving from child\n");
        if(strcmp(buffer, "B")==0){
            fprintf(stderr,"Parent success recieve child's reply");
        }
        continue;
    }while(true);
}
int main(int argc, char** argv){

    pid_t pid = fork();
    int pipe1[2];
    int pipe2[2];

    if (pipe(pipe1)==-1 || pipe(pipe2)==-1){
        fprintf(stderr,"pipe failed\n");
        exit(1);
    }

    if(pid > 0){
        //parent
        close(STDIN_FILENO);    //close stdin
        dup(pipe1[0]);          //replace stdin with pipe1 read
        close(STDOUT_FILENO);   //close stdout
        dup(pipe2[1]);          //replace stdout with pipe2 write
        //close pipe1 and pipe2 read write
        close(pipe1[0]);        
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
        pget_input();
        wait(0);
    }else if(pid ==0){
        //child
        close(STDOUT_FILENO);   //close stdout
        dup(pipe1[1]);          //replace stdout with pipe1 write
        close(STDIN_FILENO);    //close stdin
        dup(pipe2[0]);          //replace stdin with pipe2 read

        //close pipe1 and pipe2 read write
        close(pipe1[0]);        
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);

        execl("./child", "not matter", NULL);
        perror("execvp failed");
           exit(1);

    }else{
        fprintf(stderr,"fork failed\n");
        exit(1);
    }
    fprintf(stderr,"Exiting\n");
    exit(1);

}

where ./child:

bool cget_input(void){
    char buffer[80], command[80];
    fprintf(stderr,"Child trying receive from parent\n");
    do{
        if (!fgets(buffer, 20, stdin)) {
            fprintf(stderr,"child failed to receive from parent\n");
            return false;                                        
        }
        sscanf(buffer, "%s", command);
        if(strcmp(buffer, "A") == 0){
            fprintf(stderr,"Child received 'A' from Parent and sending out 'B'\n");
            fprintf(stdout, "B");
        }
        continue;
    }while(true);
}
int main ()
{

    if(!cget_input()){
        return 0;
    }

    return 1;
}

As result, both parent and child's stdin didn't receive anything, didn't go pass

if (!fgets(buffer, 20, stdin)) 

Can someone point out what went wrong in my code? Thank you,

1
I don't see how you replace stdin/out with your pipes. Also I don't see areason for it, as you are using fprintf and fgets anyway, which are not defaulting to stdio. Why not to pass it your pipes instead of messiong with stdio?Eugene Sh.
it's part of my assignment.Tran Van Boi
basically, the task is to create a game that can communicate with HUB through stdin and stdoutTran Van Boi

1 Answers

2
votes

You must set up the pipes before you fork.

Here is an outline of the order things need to be done:

  1. Create pipes with pipe()
  2. Fork
  3. Parent and child each close the correct ends of their pipes.
  4. If desired, parent and child can redirect stdout, stdin with dup() and close()
  5. At this point, you can exec() a new program in the child process which doesn't need to know about the redirection that has happened.

After a fork, the parent and child are two different processes and the parent has no power to modify the file descriptors of child at that point. Any shared file descriptors must be set up before a fork.