4

I need to create communication between parent and a forked child using pipes. The parent will send 0, the child will send back 1, the parent will reply 2, etc., until the counter reaches 5. Then both processes will terminate.

I tried to implement this using two pipes:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int fd[2];
    int fd2[2];

    int val = 0;

    // create pipe descriptors
    pipe(fd);
    pipe(fd2);

    // fork() returns 0 for child process, child-pid for parent process.
    if (fork() != 0) {
            ///0. Send: 0
            // parent: writing only, so close read-descriptor.
            close(fd[0]);

            // send the value on the write-descriptor.
            val = 0;
        resend:
            write(fd[1], &val, sizeof(val));
            printf("0.Parent(%d) send value: %d\n", getpid(), val);

            // close the write descriptor
            close(fd[1]);

            ///3. Receive 1;
            close(fd2[1]);

            // now read the data
            read(fd2[0], &val, sizeof(val));
            printf("3.Parent(%d) received value: %d\n", getpid(), val);

            // close the read-descriptor
            close(fd2[0]);
            wait(NULL);
            val++;
            if (val < 6)
                goto resend;
            else
                return 0;

    } else {   // child: reading only, so close the write-descriptor
        childStart:
        wait(NULL);

        ///1. receive: 0
            close(fd[1]);

            // now read the data (will block)
            read(fd[0], &val, sizeof(val));
            printf("1.Child(%d) received value: %d\n", getpid(), val);

            // close the read-descriptor
            //close(fd[0]);

            ///2. Send: 1
            // parent: writing only, so close read-descriptor.
            close(fd2[0]);

            // send the value on the write-descriptor.
            val = val + 1;
            write(fd2[1], &val, sizeof(val));
            printf("2.Child(%d) send value: %d\n", getpid(), val);

            // close the write descriptor
            close(fd2[1]);
            if(val <5) {
                wait(NULL);
                goto childStart;
            }
            else
                return 0;
        }
        ///////////////////////////////////////////////////////////////////////////////////

    return 0 ;
    }

I get the follow output:

0.Parent(120978) send value: 0
1.Child(120979) received value: 0
2.Child(120979) send value: 1
1.Child(120979) received value: 1
2.Child(120979) send value: 2
1.Child(120979) received value: 2
2.Child(120979) send value: 3
1.Child(120979) received value: 3
2.Child(120979) send value: 4
1.Child(120979) received value: 4
2.Child(120979) send value: 5
3.Parent(120978) received value: 1
0.Parent(120978) send value: 2
3.Parent(120978) received value: 2
0.Parent(120978) send value: 3
3.Parent(120978) received value: 3
0.Parent(120978) send value: 4
3.Parent(120978) received value: 4
0.Parent(120978) send value: 5
3.Parent(120978) received value: 5

How can I make the processes wait for each other's message?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
David
  • 75
  • 1
  • 7
  • `resend: if (val < 6) goto resend;` Just use a `while` loop... You do `close(fd[1]);` then `goto resend` and reuse `write(fd[1],`. Well, once you close `fd[1]` you can't use it later. – KamilCuk May 22 '20 at 13:29
  • 2
    Re "*How can I make the processes wait for each other's message?*" What do you mean? You clearly see the parent waiting for a reply before sending the next number. Same in the child – ikegami May 22 '20 at 13:30
  • 1
    You're closing the file descriptors in the loop, which is breaking everything; and you're not checking the exit codes from the read/writes, so after closing the file descriptors every read/write is non-blocking and returns failure, which means the variable doesn't get sent or overwritten. – Anya Shenanigans May 22 '20 at 13:32
  • Why are you calling `wait` in the child? – William Pursell May 22 '20 at 13:38

1 Answers1

2

Thera are a lot of problems in your code, i changed a lot of things, the result is this:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>

int main(int argc, char *argv[])
{
    int signo;
    pid_t child_pid,parent_pid;
    sigset_t newmask;
    int fd[2];
    int fd2[2];

    int val = 0;

    // create pipe descriptors
    pipe(fd);
    pipe(fd2);

    // create mask for SIGUSR1
    sigemptyset(&newmask);
    sigaddset(&newmask,SIGUSR1);
    sigaddset(&newmask,SIGUSR2);
    sigprocmask(SIG_BLOCK,&newmask,NULL);

    parent_pid = getpid();

    // fork() returns 0 for child process, child-pid for parent process.
    if ((child_pid = fork()) != 0) {
      // Close unused file descriptors
      close(fd[0]);
      close(fd2[1]);

      // send the value on the write-descriptor.
      for(val = 0; val < 6; val++){
        write(fd[1], &val, sizeof(val));
        printf("0.Parent(%d) send value: %d\n", getpid(), val);
        sigwait(&newmask,&signo);
        kill(parent_pid,SIGUSR2);

        // now read the data
        read(fd2[0], &val, sizeof(val));
        printf("3.Parent(%d) received value: %d\n", getpid(), val);
        sigwait(&newmask,&signo);
        kill(parent_pid,SIGUSR2);
      }

      return 0;

    } else {   // child: reading only, so close the write-descriptor
      // Closing unused file descriptors
      close(fd[1]);
      close(fd2[0]);


      for(; val <= 5; val++){
        // now read the data (will block)
        read(fd[0], &val, sizeof(val));
        printf("1.Child(%d) received value: %d\n", getpid(), val);
        kill(child_pid,SIGUSR1);
        sigwait(&newmask,&signo);

        // send the value on the write-descriptor.
        write(fd2[1], &val, sizeof(val));
        printf("2.Child(%d) send value: %d\n", getpid(), val);
        kill(child_pid,SIGUSR1);
        sigwait(&newmask,&signo);
      }

      wait(NULL);

      return 0;
    }
}

Your mistakes:

output:

0.Parent(14956) send value: 0
1.Child(14957) received value: 0
2.Child(14957) send value: 0
3.Parent(14956) received value: 0
0.Parent(14956) send value: 1
1.Child(14957) received value: 1
2.Child(14957) send value: 1
3.Parent(14956) received value: 1
0.Parent(14956) send value: 2
1.Child(14957) received value: 2
2.Child(14957) send value: 2
3.Parent(14956) received value: 2
0.Parent(14956) send value: 3
1.Child(14957) received value: 3
2.Child(14957) send value: 3
3.Parent(14956) received value: 3
0.Parent(14956) send value: 4
1.Child(14957) received value: 4
2.Child(14957) send value: 4
3.Parent(14956) received value: 4
0.Parent(14956) send value: 5
1.Child(14957) received value: 5
2.Child(14957) send value: 5
3.Parent(14956) received value: 5
Holeryn
  • 387
  • 1
  • 4
  • 11