简体   繁体   中英

Processes not executing in expected order; fork() and waitpid()

I wrote a program that calls fork() two times, generating three children and a parent.

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

int main() {
    int child1 = fork();
    int child2 = fork();

    // Check for error
    if (child1 < 0 || child2 < 0) {
        fprintf(stderr, "A fork failed :(\n");
        exit(1);
    }

    // Parent Process
    if (child1 > 0 && child2 > 0) {
        waitpid(child1, NULL, 0);
        waitpid(child2, NULL, 0);
        printf("I'm the parent\n");
    }
    // Child B -- CONFUSION AREA --
    else if (child1 > 0 && child2 == 0) {
        waitpid(child1, NULL, 0); // Not waiting for process to finish
        printf("I'm child B\n");
    }
    // Child A
    else if (child1 == 0 && child2 > 0) {
        waitpid(child2, NULL, 0);
        printf("I'm child A\n");
    }
    // Child C
    else if (child1 == 0 && child2 == 0) {            
        printf("I'm child C\n");
    }

    return 0;
}

I'm trying to print out

I'm child C
I'm child A
I'm child B
I'm the parent

but instead, the program prints out

I'm child B
I'm child C
I'm child A
I'm the parent

I'm confused why child B isn't waiting for child1 process to finish?

I drew a process tree to try and understand what is going on, and my understanding is that it looks like:

/*

         Parent (15543)
         child1 = 15544;
         child2 = 15545
           /       \
          /         \
         /           \
        A (15544)     B (15545)
     child1 = 0;      child1 = 15544;
     child2 = 15546;  child2 = 0;
        /
       /
      /
     C (15546)
     child1 = 0;
     child2 = 0;


*/

When child B calls waitpid() the call fails and returns -1 because the parent is already waiting on child A, and you can't reap a child process twice.

For the behavior you want, you may be better off using inter-process semaphores to synchronize your process execution. Try including semaphore.h and take a look at the documentation for sem_init() .

When you execute the first fork() , both processes (parent and child) go to the second fork() and generate the two other processes you see in the tree. This is the reason you see a grandchild in the output. You think there are only two forks executed, so two children are expected, but you have not realized that the second fork() is actually executed by two processes: the parent and the child of the first fork() call .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM