user3751012
user3751012

Reputation: 551

Not Understanding the PIPE Program

What I know about PIPE is that it is used for a unidirectional communication and it helps to communicate between two related process. I have got the below PIPE programming code example from a book. I am trying to understand the code using printf and printing out all the points after every line of the code. But I am not understanding how the program is running after each and every line. My code is below:

PIPE:

//using PIPE to communicate with a child process

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

/* Write COUNT copies of MESSAGE to filename, pausing for a second
 between each. */

void writer (const char* message, int count, FILE* filename)
{
    for (; count > 0 ; -- count) {
        printf("point 13\n");
        /* Write the message to the filename, and send it off immediately.*/
        fprintf (filename, "%s\n", message);
        printf("point 14\n");
        fflush (filename);
        printf("point 15\n");
        /* Snooze a while. */
        sleep (1);
    }
}


/* Read random strings from the filename as long as possible.
 */

void reader (FILE* filename)
{
    char buffer[1024];
    /* Read until we hit the end of the filename. fgets reads until
     either a newline or the end-of-FILE. */
    printf("point 16\n");
    while (!feof (filename) && !ferror (filename) && fgets (buffer, sizeof (buffer), filename) != NULL)
        fputs (buffer, stdout);
    printf("point 17\n");
}


int main ()
{
    int fds[2];
    pid_t pid;
    printf("point 1\n");

    /* Create a pipe. FILE descriptors for the two ends of the pipe are
     placed in fds. */
    pipe (fds);
    printf("point 2\n");
    /* Fork a child process. */
    pid = fork ();
    printf("point 3\n");

    if (pid == (pid_t) 0)
    {
        FILE* filename;
        printf("point 4\n");
        /* This is the child process. Close our copy of the write end of
         the FILE descriptor. */
        close (fds[1]);
        printf("point 5\n");
        /* Convert the read FILE descriptor to a FILE object, and read
         from it. */
        filename = fdopen (fds[0], "r");
        printf("point 6\n");
        reader (filename);
        printf("point 7\n");

        close (fds[0]);
        printf("point 8\n");
    }

    else 
    {
        /* This is the parent process. */
        FILE* filename;
        /* Close our copy of the read end of the FILE descriptor. */
        close (fds[0]);
        printf("point 9\n");
        /* Convert the write FILE descriptor to a FILE object, and write
         to it. */
        filename = fdopen (fds[1], "w");
        printf("point 10\n");
        writer ("I want to learn c programming!", 5, filename);
        printf("point 11\n");
        close (fds[1]);
        printf("point 12\n");
    }
    return 0;
}

I really need to understand the code. If I run my code then I am getting output like below in the Linux terminal but I am not sure why after the point 3,the point 9 is coming. Again after point 9 why point 3,4,5,10. Details explanation will help me.

point 1
point 2
point 3
point 9
point 3
point 4
point 5
point 10
point 13
point 14
point 15
point 6
point 16
I want to learn c programming!
point 13
point 14
point 15
I want to learn c programming!
point 13
point 14
point 15
I want to learn c programming!
point 13
point 14
point 15
I want to learn c programming!
point 13
point 14
point 15
I want to learn c programming!
point 11
point 12
point 17
point 7
point 8

Upvotes: 0

Views: 567

Answers (1)

prince
prince

Reputation: 1149

pipe(int[]) function returns an array of size two integers. You need to understand the basic concepts here. A pipe can be used for unidirectional communication same as a water pipe. One thing you need to understand here is pipe is internally a file. So, as we use file descriptors for reading and writing content from/into a file similarly we need descriptors for reading/writing from/to a pipe. Now in your program when pipe(fds) is executed, a pipe is created and two descriptors are created for reading and writing into this pipe. These descriptors are fds[0](read end) and fds[1](write end).

Now, you need to understand about fork() here, this function created a new process(child process) by duplicating the existing process. Immediately after calling fork(), in child if is executed as fork returns 0 in child process and in parent the if condition fails as fork returns pid of child in parent process, hence else is executed. Rest you can observe your code.

Inside if you are closing fds[1], this will now enable your child process to only have read file descriptor for pipe and you are closing fds[0] in parent, this will enable your parent to have only write descriptor for pipe. Now, your child is able to only read from pipe and parent is only able to write from the pipe and you can observe the communication is from parent to child(parent is writing, child is reading). If you want a reverse communication than you need to create a new pipe. So, one pipe can be used for communication in one direction.

Now, you can understand rest of the program simply by understanding how a parent and child process will execute after fork. Now whichever process gets CPU time that process is executed, in this way you get an interleaved execution of child and parent process leaving you with the above output.

Upvotes: 3

Related Questions