Как дождаться завершения всех дочерних процессов, вызываемых fork ()?

Я создаю несколько процессов, и я хочу измерить, сколько времени уходит на выполнение всей задачи, то есть когда все процессы, разветвленные, завершены. Посоветуйте, пожалуйста, как заставить родительский процесс ждать завершения всех дочерних процессов? Я хочу убедиться, что остановил таймер в нужный момент.

Вот как код, который я использую:

#include <iostream>
#include <string>
#include <fstream>
#include <sys/time.h>
#include <sys/wait.h>

using namespace std;

struct timeval first,  second,  lapsed;
struct timezone tzp; 

int main(int argc, char* argv[])// query, file, num. of processes.
{

    int pCount = 5; // process count

    gettimeofday (&first, &tzp); //start time

    pid_t* pID = new pid_t[pCount];

    for(int indexOfProcess=0; indexOfProcess<pCount; indexOfProcess++)
    {
        pID[indexOfProcess]= fork();

        if (pID[indexOfProcess] == 0)                // child
        {
            // code only executed by child process

            // magic here

            // The End
            exit(0);
        }
        else if (pID[indexOfProcess] < 0)    // failed to fork
        {
            cerr << "Failed to fork" << endl;
            exit(1);
        }
        else                         // parent
        {
            // if (indexOfProcess==pCount-1) and a loop with waitpid??

            gettimeofday (&second, &tzp); //stop time
            if (first.tv_usec > second.tv_usec)
            {
                second.tv_usec += 1000000;
                second.tv_sec--;
            }

            lapsed.tv_usec = second.tv_usec - first.tv_usec;
            lapsed.tv_sec = second.tv_sec - first.tv_sec; 

            cout << "Job performed in " <<lapsed.tv_sec << " sec and " << lapsed.tv_usec    << " usec"<< endl << endl;

        }

    }//for

}//main

C: stackoverflow.com/questions/19461744/…

Ciro Santilli新疆棉花TRUMP BAN BAD 14.12.2018 02:57
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
1
69 181
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я верю, что ждать системного вызова выполнит то, что вы ищете.

Обратите внимание, что wait () ожидает только одного дочернего процесса, поэтому вы должны вызывать wait () столько раз, сколько дочерних процессов. В качестве альтернативы вы можете использовать waitpid () для ожидания определенного дочернего элемента, но, опять же, вам придется делать это для каждого ребенка.

Adam Rosenfield 11.11.2008 04:17

Вызовите wait (или waitpid) в цикле, пока не будут учтены все дочерние элементы.

В этом случае все процессы синхронизируются в любом случае, но в целом предпочтительнее подождать, когда можно будет выполнить больше работы (например, пул рабочих процессов), поскольку оно вернется при изменении состояния первого доступного процесса.

Не могли бы вы предоставить мне образец кода? Должен признать, я не совсем понимаю, какие флаги мне следует использовать ...

Kamil Zadora 11.11.2008 04:18

Самый простой способ - сделать

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

Это не сработает, если wait() выйдет из строя по какой-либо причине, кроме того факта, что не осталось детей. Итак, с некоторой проверкой ошибок это становится

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

См. Также страницу руководства wait(2).

вам все равно нужно учитывать количество дочерних процессов

BCS 11.11.2008 04:27

Неа. Когда дочерних элементов больше нет, wait вернет -1, а errno будет установлено значение ECHILD. Не оптимально, но для его использования должно хватить.

gnud 11.11.2008 04:28

Если это нежелательно, то сначала игнорируйте сигналы. Это не уникально для обработки процессов -

gnud 12.11.2008 13:24
for (int i = 0; i < pidCount; i++) {
    while (waitpid(pids[i], NULL, 0) > 0);
}

Он не будет ждать в правильном порядке, но остановится вскоре после смерти последнего ребенка.

Ответ принят как подходящий

Я бы переместил все после строки «else // parent» вниз, за ​​пределы цикла for. После цикла вилок выполните еще один цикл for с помощью waitpid, затем остановите часы и сделайте все остальное:

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

Я предположил, что если дочерний процесс не может нормально завершиться со статусом 0, значит, он не завершил свою работу, и, следовательно, тест не смог предоставить достоверные данные о времени. Очевидно, что если дочерние процессы предполагаемый должны быть уничтожены сигналами или выйдут из ненулевых статусов возврата, вам придется соответственно изменить проверку ошибок.

Альтернатива с использованием ожидания:

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);
        }
    }
}

Он не сообщает вам, какой процесс в последовательности завершился ошибкой, но если вам не все равно, вы можете добавить код, чтобы найти его в массиве pids и вернуть индекс.

Во втором фрагменте кода выше есть опечатка слабый: имя сигнала ошибки в if (done == -1) { ... } должно быть ECHILD, а не ECHLD.

Vicky Chijwani 19.01.2012 00:31

Другие вопросы по теме