Domanda

Sto eseguendo il fork di una serie di processi e desidero misurare il tempo necessario per completare l'intera attività, ovvero quando vengono completati tutti i processi a fork. Si prega di avvisare come attendere il completamento del processo parent fino al termine di tutti i processi child? Voglio assicurarmi di interrompere il timer al momento giusto.

Ecco come codice che uso:

#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
È stato utile?

Soluzione

Sposterei tutto dopo la riga " else // parent " in basso, al di fuori del ciclo for. Dopo il ciclo di forchette, fai un altro per ciclo con waitpid, quindi ferma l'orologio e fai il resto:

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

Ho ipotizzato che se il processo figlio non termina normalmente con uno stato 0, allora non ha completato il suo lavoro e quindi il test non ha prodotto dati di temporizzazione validi. Ovviamente se i processi figlio sono supposti essere uccisi dai segnali o escono stati di ritorno diversi da 0, allora dovrai cambiare il controllo degli errori di conseguenza.

Un'alternativa che utilizza 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);
        }
    }
}

Questo non ti dice quale processo in sequenza non è riuscito, ma se ti interessa puoi aggiungere il codice per cercarlo nell'array pids e recuperare l'indice.

Altri suggerimenti

Il metodo più semplice è fare

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

Questo non funzionerà se wait () fallisce per qualche motivo diverso dal fatto che non sono rimasti bambini. Quindi, con qualche controllo degli errori, questo diventa

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

Vedi anche la pagina di manuale wait (2) .

Chiama wait (o waitpid) in un ciclo fino a quando tutti i bambini non vengono contabilizzati.

In questo caso, tutti i processi si stanno comunque sincronizzando, ma in generale si preferisce attendere quando è possibile svolgere più lavoro (ad es. pool di processi di lavoro), poiché tornerà quando cambia il primo stato del processo disponibile.

Credo che wait system call realizzerà ciò che stai cercando.

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

Non aspetterà nel giusto ordine, ma si fermerà poco dopo la morte dell'ultimo figlio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top