2009-10-02 12 views
12

Nel mio programma eseguo (in parallelo) processi figlio in un ciclo while finito e eseguo exec su ognuno di essi. Voglio che il processo padre riprenda l'esecuzione (il punto dopo questo ciclo while) solo dopo che tutti i bambini sono terminati. Come dovrei farlo?In attesa di tutti i processi figlio prima che il genitore riprenda l'esecuzione UNIX

ho provato diversi approcci. In un approccio, ho creato parent in pausa dopo ciclo e inviato alcune condizioni dal gestore SIGCHLD solo quando waitpid ha restituito errore ECHILD (nessun figlio rimanente) ma il problema che sto affrontando in questo approccio è ancora prima che il genitore abbia terminato di forgiare tutti i processi, retStat diventa -1

void sigchld_handler(int signo) { 
     pid_t pid; 
     while((pid= waitpid(-1,NULL,WNOHANG)) > 0); 
     if(errno == ECHILD) { 
      retStat = -1; 
     } 
    } 

    **//parent process code** 
    retStat = 1; 
    while(some condition) { 
     do fork(and exec); 
    } 

    while(retStat > 0) 
     pause(); 
//This is the point where I want execution to resumed only when all children have finished 

risposta

21

Invece di chiamare waitpid nel gestore del segnale, perché non creare un loop dopo aver biforcuta tutti i processi come segue:

while (pid = waitpid(-1, NULL, 0)) { 
    if (errno == ECHILD) { 
     break; 
    } 
} 

Il programma dovrebbe appendere in loop fino a quando non ci sono più bambini. Quindi cadrà e il programma continuerà. Come bonus aggiuntivo, il ciclo si bloccherà su waitpid mentre i bambini sono in esecuzione, quindi non è necessario un ciclo occupato durante l'attesa.

È inoltre possibile utilizzare wait(NULL) che dovrebbe essere equivalente a waitpid(-1, NULL, 0). Se non c'è nient'altro che devi fare in SIGCHLD, puoi impostarlo su SIG_IGN.

+0

Ho bisogno di dare l'opzione WNOHANG perché se ci sono molti bambini che consegnano il segnale SIGCHLD quasi allo stesso tempo, e poiché i segnali non sono in coda in UNIX, se io uso 0, allora sarò in grado di catturare solo un segnale quindi gli zombi essere lasciato in giro. – avd

+0

Solo per aggiungere un po ', il -1 controllerà ogni pid figlio (potrebbe usare anche WAIT_ANY per chiarezza). – amischiefr

+0

@aditya: i processi zombi ti stanno solo aspettando di chiamare wait() (o wait_pid()) su di essi. Non appena lo fai, spariranno, indipendentemente dal fatto che tu abbia preso il segnale. Quindi il ciclo wait() dopo il ciclo fork() rimuoverà tutti gli zombi. –

0

credo che si dovrebbe utilizzare la chiamata waitpid(). Ti permette di aspettare "qualsiasi processo figlio", quindi se lo fai il giusto numero di volte, dovresti essere d'oro.

Se non funziona (non sono sicuro circa le garanzie), si potrebbe fare l'approccio a forza bruta seduto in un ciclo, facendo un waitpid() con l'opzione NOHANG su ciascuno di vostro figlio PID, e quindi ritardando per un po 'prima di fare nuovamente.

+0

Si prega di consultare il codice, ho fatto esattamente la stessa cosa che stai dicendo. – avd

+0

@aditya: Uh, no, il mio suggerimento significa fare come suggerisce jborque, non ho detto nulla sull'uso di un gestore di segnale. – unwind

Problemi correlati