How to wait until all child processes called by fork() complete?

前端 未结 5 806
北恋
北恋 2020-12-08 03:28

I am forking a number of processes and I want to measure how long it takes to complete the whole task, that is when all processes forked are completed. Please advise how to

相关标签:
5条回答
  • 2020-12-08 03:36

    Call wait (or waitpid) in a loop until all children are accounted for.

    In this case, all processes are synchronizing anyway, but in general wait is preferred when more work can be done (eg worker process pool), since it will return when the first available process state changes.

    0 讨论(0)
  • 2020-12-08 03:46

    The simplest method is to do

    while(wait() > 0) { /* no-op */ ; }
    

    This will not work if wait() fails for some reason other than the fact that there are no children left. So with some error checking, this becomes

    int status;
    [...]
    do {
        status = wait();
        if(status == -1 && errno != ECHILD) {
            perror("Error during wait()");
            abort();
        }
    } while (status > 0);
    

    See also the manual page wait(2).

    0 讨论(0)
  • 2020-12-08 03:46

    I believe the wait system call will accomplish what you are looking for.

    0 讨论(0)
  • 2020-12-08 03:54
    for (int i = 0; i < pidCount; i++) {
        while (waitpid(pids[i], NULL, 0) > 0);
    }
    

    It won't wait in the right order, but it will stop shortly after the last child dies.

    0 讨论(0)
  • 2020-12-08 04:01

    I'd move everything after the line "else //parent" down, outside the for loop. After the loop of forks, do another for loop with waitpid, then stop the clock and do the rest:

    for (int i = 0; i < pidCount; ++i) {
        int status;
        while (-1 == waitpid(pids[i], &status, 0));
        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
            cerr << "Process " << i << " (pid " << pids[i] << ") failed" << endl;
            exit(1);
        }
    }
    
    gettimeofday (&second, &tzp); //stop time
    

    I've assumed that if the child process fails to exit normally with a status of 0, then it didn't complete its work, and therefore the test has failed to produce valid timing data. Obviously if the child processes are supposed to be killed by signals, or exit non-0 return statuses, then you'll have to change the error check accordingly.

    An alternative using wait:

    while (true) {
        int status;
        pid_t done = wait(&status);
        if (done == -1) {
            if (errno == ECHILD) break; // no more child processes
        } else {
            if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
                cerr << "pid " << done << " failed" << endl;
                exit(1);
            }
        }
    }
    

    This one doesn't tell you which process in sequence failed, but if you care then you can add code to look it up in the pids array and get back the index.

    0 讨论(0)
提交回复
热议问题