Question

Je suis en train de forger un certain nombre de processus et je veux mesurer le temps nécessaire pour achever toute la tâche, c’est-à-dire lorsque tous les processus créés sont terminés. Veuillez indiquer comment faire en sorte que le processus parent attende que tous les processus enfants soient terminés. Je veux m'assurer que j'arrête le chronomètre au bon moment.

Voici un code que j'utilise:

#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
Était-ce utile?

La solution

Je déplacerais tout ce qui suit la ligne " else // parent " bas, en dehors de la boucle for. Après la boucle de forks, faites une autre boucle for avec waitpid, puis arrêtez l'horloge et faites le reste:

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

J'ai supposé que si le processus enfant échouait normalement avec l'état 0, il ne finissait pas son travail et que, par conséquent, le test ne permettait pas de générer des données de synchronisation valides. Évidemment, si les processus enfants sont supposés être tués par des signaux ou quitter les états de retour non-0, vous devrez alors modifier le contrôle d'erreur en conséquence.

Une alternative utilisant 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);
        }
    }
}

Celui-ci ne vous dit pas quel processus en séquence a échoué, mais si vous le souhaitez, vous pouvez ajouter du code pour le rechercher dans le tableau pids et récupérer l'index.

Autres conseils

La méthode la plus simple consiste à faire

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

Cela ne fonctionnera pas si wait () échoue pour une raison autre que le fait qu'il ne reste plus d'enfants. Donc, avec quelques erreurs de vérification, cela devient

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

Voir aussi la page de manuel wait (2) .

Appelez wait (ou waitpid) dans une boucle jusqu'à ce que tous les enfants soient comptabilisés.

Dans ce cas, tous les processus se synchronisent de toute façon, mais l'attente est généralement préférable lorsque davantage de travail peut être effectué (par exemple, un pool de processus de travail), car il sera renvoyé lorsque le premier état de processus disponible sera modifié.

Je pense que le appel système en attente répondra à vos attentes.

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

Il n'attendra pas dans le bon ordre, mais il s'arrêtera peu de temps après le décès du dernier enfant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top