David
David

Reputation: 75

Two-way communication with pipes

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?

Upvotes: 4

Views: 2726

Answers (1)

Holeryn
Holeryn

Reputation: 397

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

Upvotes: 2

Related Questions