user1595723
user1595723

Reputation: 41

How to use "anonymous" pipes for process synchronization in C?

I have been having a hard time understanding how the command pipe() works in C. As far as I know anonymous pipes are used to send/receive information between two "related" processes.
I am finding the conditions for reading and writing into/from the corresponding file descriptor very confusing and do not understand why the read fd must be closed in order to write and viceversa, and how this, in turn can be used to block a process until another has read or written.

How can pipes be used to synchronize processes? For instance how would the following process hierarchy be implemented using pipe()?

A / B ----D\
  \ C ------\
             E


-A must finish before B and C are created.
-B must finish before D is created.
-C and C must finish before E is created.
-B and C may finish in any order

Many thanks for your help

Upvotes: 2

Views: 2444

Answers (2)

Tanmoy Bandyopadhyay
Tanmoy Bandyopadhyay

Reputation: 985

I have simulated the process synchronisation that you have mentioned and also provided comments. Hope the concept will be clear now.

Note here no data is read here over the pipe, it is only used to achieve synchronisation, by using the blocking nature of the read function, when write end(s) of a pipe is still open.

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#define MAXBUF 1

int main(){

    int ret, i, fd[2];
    char buf[MAXBUF];

    //Create a Pipe
    pipe(fd);

    ret = fork();//Creating process A
    if (0 == ret)
    {
            printf("Process - A created\n");
            exit(0);
    }
    //I need to wait till Process - A completes
    //Let me close my write end else I will be blocked for ever in the loop below
    close(fd[1]);

    //Waiting over reading the pipe -> The loop will come out when Process A exits
    //Why ->since all the write ends of the pipe are closed, so read returns 0
    while ((ret = read(fd[0], buf, MAXBUF)) > 0)
    {
            //Just Wait, the read blocks till A exits and then read returns 0
    }
    //Again a pipe to synchronise B and C
    pipe(fd);

    //Lets Create Now  B and C

    ret = fork();
    if (0 == ret)
    {
            printf("Process - B created\n");
            exit(0);
    }
    ret = fork();
    if (0 == ret)
    {
            printf("Process - C created\n");
            exit(0);

    }
    //Let me close my Write End of pipe
    close(fd[1]);

    //Here Waiting for Termination of both B and C who can terminate in any order.
    while ((ret = read(fd[0], buf, MAXBUF)) > 0)
    {
            //This loop will turn false only if both B & C have exited.
            //Since both the write ends of the pipe that
            //were there in B and C will no longer be available
            //after they exit and thus the read will return 0
            //Just Wait ..Do nothing
    }
    //Now all A, B, C are finished.
    //Create D and E
    ret = fork();
    if (0 == ret)
    {
            printf("Process - D created\n");
            exit(0);
    }
    ret = fork();
    if (0 == ret)
    {
            printf("Process - E created\n");
            exit(0);

    }
//Here let the main process wait for all the 5 Child to complete
    //This is not needed, but I gave given so that the Shell
    //Prompt is shown after the code exits..
    //If this is deleted then you need to press return
    //to get back the shell prompt after the code completes execution.
    for (i = 0; i < 5; i++)
    {
            wait(NULL);
    }

}

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409356

Pipes are not used for process synchronization, not directly anyway. Instead it's a way to communicate.

For example, a process creates a pair of pipes (one write-end and one read-end), then forks so a new child process is created. The parent can then send data to the child process through the pipe.

Upvotes: 1

Related Questions