Я создаю несколько процессов, и я хочу измерить, сколько времени уходит на выполнение всей задачи, то есть когда все процессы, разветвленные, завершены. Посоветуйте, пожалуйста, как заставить родительский процесс ждать завершения всех дочерних процессов? Я хочу убедиться, что остановил таймер в нужный момент.
Вот как код, который я использую:
#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





Я верю, что ждать системного вызова выполнит то, что вы ищете.
Обратите внимание, что wait () ожидает только одного дочернего процесса, поэтому вы должны вызывать wait () столько раз, сколько дочерних процессов. В качестве альтернативы вы можете использовать waitpid () для ожидания определенного дочернего элемента, но, опять же, вам придется делать это для каждого ребенка.
Вызовите wait (или waitpid) в цикле, пока не будут учтены все дочерние элементы.
В этом случае все процессы синхронизируются в любом случае, но в целом предпочтительнее подождать, когда можно будет выполнить больше работы (например, пул рабочих процессов), поскольку оно вернется при изменении состояния первого доступного процесса.
Не могли бы вы предоставить мне образец кода? Должен признать, я не совсем понимаю, какие флаги мне следует использовать ...
Самый простой способ - сделать
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).
вам все равно нужно учитывать количество дочерних процессов
Неа. Когда дочерних элементов больше нет, wait вернет -1, а errno будет установлено значение ECHILD. Не оптимально, но для его использования должно хватить.
Если это нежелательно, то сначала игнорируйте сигналы. Это не уникально для обработки процессов -
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.
C: stackoverflow.com/questions/19461744/…