Search code examples
cpipefork

How processes work sequentially with C pipe?


I want to do that 2 child processes will put their names and wait until other process put his name. For instance, if there are first and second process, first will put her name and will wait for other's name in screen. So I want to work with processes and I wanna to see they are working sequentially.

Output:

first
second
first
second
first
second

I just tried something about C(linux).

int main(void) 
{    
    pid_t child_a, child_b;
    int pipe1[2], pipe2[2];
    char mesazhi1[] = "first";
    char mesazhi2[] = "second";

    char buf[1024];

    int first_pipe = pipe(pipe1);
    pipe(pipe2);

    if(first_pipe == -1){
        perror("pipe");
        exit(1);
    }

    child_a = fork();

    if (child_a == 0) 
    {
        /* Child A code */
        int i;
        for (i = 0; i < 3; i++)
        {
            write(pipe1[1],mesazhi1, strlen(mesazhi1) + 1);
            //printf("first\n");
            int a = read(pipe2[0], buf, strlen(mesazhi2) + 1); 
            printf("%s - %d\n", buf, a);
        }
    } 
    else 
    {
        child_b = fork();

        if (child_b == 0) 
        {
            int i;
            for (i = 0; i < 3; i++)
            {   
                write(pipe2[1],mesazhi2, strlen(mesazhi2) + 1);
                //printf("second\n");
                int a = read(pipe1[0], buf, strlen(mesazhi1) + 1); 
                printf("%s - %d\n", buf, a);
            }
        } 
        else 
        {
            /* Parent Code */

            int returnStatusA,returnStatusB;    
            waitpid(child_a, &returnStatusA, 0);  // Parent process waits here for child to terminate.
            waitpid(child_b, &returnStatusB, 0);  // Parent process waits here for child to terminate.


            if (returnStatusA == 0 && returnStatusB == 0)  // Verify child process terminated without error.  
            {
               printf("%s\n", "The child processes terminated normally.\n"); 
            }

            if (returnStatusA == 1 && returnStatusB == 1)      
            {
               printf("%s\n", "The child processes terminated with an error!. \n" );    
            }
        }
    }
}

It is putting name randomly. I mean that I think, sometimes second process works faster than first. Output like that:

first
second
second
first
second
...

So why second process doesn't wait for first one, because I think that read() function should wait until there is something in pipe1.


Solution

  • In the posted code, both processes write to their respective pipes, and then read. After that, it's a race to see which process gets to print first.

    For a more controlled situation, have child B call read and printf before calling write. That way B has to wait for A before printing, and vice versa.

    if (child_b == 0) 
    {
        int i;
        for (i = 0; i < 3; i++)
        {   
            int a = read(pipe1[0], buf, strlen(mesazhi1) + 1); 
            printf("%s - %d\n", buf, a);
            write(pipe2[1],mesazhi2, strlen(mesazhi2) + 1);
        }
    }