GreenSkies
GreenSkies

Reputation: 141

Properly Piping Between Processes

The problem: Parent will read an integer from the keyboard and send a value to one of its children using a pipe. The child will take that value and square and pass it to the next child. The other child will add one to the received value. This child will then pass the value back to the parent and the parent will print to the screen. This will be repeated until EOF is given as input.

To be frank this is a lab exercise and I thought I had it down, but I'm not clear on some logic. For my code, the expected output will work the first time, but only the first time. Any input given after the first run will lead to no response or improper behavior( such as passing value to child and nothing happens).

      #include <fcntl.h>
  #include <stdio.h>
  #include <stdlib.h>
  void square_plus1()
  {
     int fd[2];
     int fd2[2];
     int fd3[3];
     int value;
     int myInt;
     int status;
     pid_t child1;
     pid_t child2;

     pipe(fd);
     pipe(fd2);
     pipe(fd3);
     child1 = fork();
     child2 = fork();

     if(child1 == 0)
     {
        close(fd3[0]);
        close(fd3[1]);

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

        read(fd[0],&value,sizeof(value));
        close(fd[0]);
        printf("Child1(%d) received value: %d\n", getpid(), value);
        value = value * value;
        write(fd2[1],&value,sizeof(value));
        close(fd2[1]);
        exit(0);
     }
     else if(child2 == 0)
     {
        close(fd[0]);
        close(fd[1]);

        close(fd2[1]);
        close(fd3[0]);

        read(fd2[0],&value,sizeof(value));
        printf("Child2(%d) received value: %d\n", getpid(), value);
        close(fd2[0]);
        value++;
        write(fd3[1],&value,sizeof(value));
        close(fd3[1]);
        exit(0);
     }
     else
     {
        while((scanf("%d", &value)) != EOF) 
        {
           write(fd[1],&value, sizeof(value));
           printf("Parent(%d) sent value: %d\n", getpid(), value);
           waitpid(child1,&status,0);
           if(status == 0)
           {
           }
           waitpid(child2,&status,0);
           if(status == 0)
           {
           }
           read(fd3[0],&value,sizeof(value));
           printf("New Value: %d\n",value);
        }

        waitpid(child1,&status,0);
        if(status == 0)
        {
           printf("Child 1 finishes normally\n");
        }
        waitpid(child2,&status,0);
        if(status == 0)
        {
           printf("Child 2 finishes normally\n");
        }
        close(fd2[0]);
        close(fd2[1]);
        close(fd[0]);
        close(fd[1]);
        close(fd3[1]);
        close(fd3[0]);
     }
  }
  int main(void)
  {
     square_plus1();
     return 0;
  }

I somewhat understand piping, but not well enough to solve the problem. Any help/references is much appreciated.

Upvotes: 2

Views: 97

Answers (1)

Aniruddh Dikhit
Aniruddh Dikhit

Reputation: 682

First of all you have four process in the mix here because of two consecutive fork() calls. This is what you have

 child1 = fork();
 child2 = fork();

After the first fork you have two processes the parent and the child. Now when you do the second fork both parent and child will add a child process each. So you have four processes active at this point in time. You may want to move the 2nd fork inside either the parent process (if child == 0)) or the child process (if (child != 0). The other thing that required addressing was that after processing the first input your child processes were exiting so next processing would not have happened in any case. Next your pipes need to be set appropriately to get this moving.

Assuming fd1, fd2 and fd3 are the pairs, here is a rought sketch of what you should do (not complete code but just to convey the picture)

    child1 = fork();
    if(child1 == 0) {
            // 1st child
            // .. code to close fds accordingly
            while (1) {
                    read(fd1[0],&value,sizeof(value));
                    printf("Child1(%d) received value: %d\n", getpid(), value);
                    value = value * value;
                    write(fd2[1],&value,sizeof(value));
            }
            exit(0);
    } else {
            child2 = fork();
            if(child2 == 0) {
                    // 2nd child process
                    // .. code to close fds accordingly
                    while (1) {
                            read(fd2[0],&value,sizeof(value));
                            printf("Child2(%d) received value: %d\n", getpid(), value);
                            value++;
                            write(fd3[1],&value,sizeof(value));
                    }
                    exit(0);
            }
            // Parent process
            // .. code to close fds accordingly
            while((scanf("%d", &value)) != EOF)
            {
                    write(fd1[1],&value, sizeof(value));
                    printf("Parent(%d) sent value: %d\n", getpid(), value);
                    read(fd3[0],&value,sizeof(value));
                    printf("New Value: %d\n",value);
            }

    }

Upvotes: 0

Related Questions