Frage

ich eine Reihe von Prozessen bin gabeln und ich möchte messen, wie lange es dauert, die gesamte Aufgabe abzuschließen, ist, dass, wenn alle gegabelt Prozesse abgeschlossen sind. Bitte beraten, wie die Eltern-Prozess warten zu machen, bis alle untergeordneten Prozesse beendet werden? Ich möchte sicherstellen, dass ich den Timer im richtigen Moment zu stoppen.

Hier ist als Code verwende ich:

#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
War es hilfreich?

Lösung

würde ich alles nach der Zeile „else // Eltern“ nach unten, außerhalb der for-Schleife bewegen. Nach der Schleife der Gabeln, mit waitpid tun andere für Schleife, dann die anzuhalten und den 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

Ich habe angenommen, dass, wenn das Kind Prozess in der Regel mit einem Status von 0 beenden ausfällt, dann hat es nicht seine Arbeit abgeschlossen hat, und deshalb hat den Test erzeugen gültige Timing-Daten fehlgeschlagen. Natürlich, wenn die Kindprozesse sind sollte durch Signale, getötet zu werden, oder Ausfahrt nicht-0 return Status, dann werden Sie die Fehlerprüfung entsprechend ändern.

Eine Alternative mit Wartezeit:

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

Dies Ihnen nicht sagen, welcher Prozess in Folge fehlgeschlagen ist, aber wenn Sie sich interessieren, dann können Sie Code hinzufügen, es in der pids Array zu suchen und den Index zurück.

Andere Tipps

Die einfachste Methode ist zu tun

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

Das wird nicht funktionieren, wenn wait() aus irgendeinem Grunde anders als die Tatsache nicht, dass es keine linken Kinder. Also mit einem gewissen Fehlerprüfung, dies wird

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

Siehe auch die Manpage wait(2).

Anrufwartezeit (oder waitpid) in einer Schleife, bis alle Kinder berücksichtigt.

In diesem Fall werden alle Prozesse synchronisieren sowieso, aber im allgemeinen Warte bevorzugt, wenn mehr Arbeit (zB Arbeitsprozess Pool) durchgeführt werden kann, da er zurückkehrt, wenn die ersten verfügbaren Prozesszustandsänderungen.

Ich glaube, die Systemaufruf warten wird erreichen, was Sie suchen.

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

Es wird nicht in der richtigen Reihenfolge warten, aber es wird aufhören, kurz nachdem das letzte Kind stirbt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top