fork()によって呼び出されるすべての子プロセスが完了するまで待つ方法は?
-
07-07-2019 - |
質問
多くのプロセスをフォークしていますが、タスク全体、つまりフォークされたすべてのプロセスが完了するまでにかかる時間を測定したいと思います。すべての子プロセスが終了するまで親プロセスを待機させる方法を教えてください。適切なタイミングでタイマーを停止するようにします。
これは私が使用するコードです:
#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
解決
&quot; else // parent&quot;行の後にすべてを移動します。ダウン、forループの外側。フォークのループの後、waitpidを使用して別のforループを実行し、クロックを停止して残りを実行します。
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で正常に終了しない場合、作業を完了できなかったため、有効なタイミングデータの生成に失敗したと想定しました。子プロセスがシグナルによって強制終了されるか、0以外のリターンステータスを終了する場合は、当然、エラーチェックを適宜変更する必要があります。
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);
}
}
}
このプロセスでは、どのプロセスが失敗したかはわかりませんが、気にする場合はコードを追加してpids配列で検索し、インデックスを取得できます。
他のヒント
最も簡単な方法は
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(またはwaitpid)を呼び出します。
この場合、すべてのプロセスはとにかく同期していますが、一般に、より多くの作業を行うことができる場合(ワーカープロセスプールなど)は、最初の使用可能なプロセスの状態が変わると戻るため、待機することをお勧めします。
waitシステムコールがあなたの探していることを達成すると信じています。
for (int i = 0; i < pidCount; i++) {
while (waitpid(pids[i], NULL, 0) > 0);
}
正しい順序で待機することはありませんが、最後の子が死亡するとすぐに停止します。