2009-10-02 5 views
12

In meinem Programm verzweige ich (parallel) untergeordnete Prozesse in einer endlichen while-Schleife und führe sie auf jedem von ihnen aus. Ich möchte, dass der übergeordnete Prozess die Ausführung (der Punkt nach dieser while-Schleife) erst wieder aufnimmt, nachdem alle untergeordneten Prozesse beendet wurden. Wie soll ich das machen?Wartet auf alle untergeordneten Prozesse, bevor der Vater die Ausführung fortsetzt. UNIX

Ich habe mehrere Ansätze ausprobiert. Bei einem Ansatz habe ich die Eltern nach der while-Schleife pausieren lassen und eine Bedingung vom SIGCHLD-Handler gesendet, nur wenn waitpid den Fehler ECHILD (kein Kind übrig) zurückgegeben hat, aber das Problem, mit dem ich konfrontiert bin, ist noch bevor Eltern alle Forks beendet haben -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 

Antwort

21

Statt waitpid im Signal-Handler aufrufen, warum nicht eine Schleife erstellen, nachdem Sie alle Prozesse gegabelt haben sich wie folgt:

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

Das Programm in der Schleife hängen sollte, bis es keine Kinder mehr sind. Dann wird es ausfallen und das Programm wird fortgesetzt. Als zusätzlichen Bonus wird die Schleife bei waitpid blockiert, während Kinder laufen, so dass Sie keine Warteschlange benötigen, während Sie warten.

Sie könnten auch wait(NULL) verwenden, was waitpid(-1, NULL, 0) entsprechen sollte. Wenn es in SIGCHLD nichts anderes zu tun gibt, können Sie es auf SIG_IGN setzen.

+0

Ich muss WNOHANG Option geben, wenn es viele Kinder gibt, die SIGCHLD-Signal fast zur gleichen Zeit liefern, und da Signale nicht in UNIX eingereiht sind, wenn ich 0 verwende, dann werde ich nur ein Signal fangen können, dann Zombies werden herum gelassen werden. – avd

+0

Nur um ein bisschen hinzuzufügen, wird die -1 gegen jede untergeordnete PID (könnte auch WAIT_ANY für Klarheit verwenden). – amischiefr

+0

@aditya: Die Zombie-Prozesse warten nur darauf, dass Sie wait() (oder wait_pid()) auf ihnen aufrufen. Sobald Sie das tun, werden sie verschwinden, unabhängig davon, ob Sie das Signal empfangen haben oder nicht. Die wait() - Schleife nach der fork() - Schleife wird also alle Zombies aufwischen. –

0

Ich denke, Sie sollten den waitpid() Aufruf verwenden. Es erlaubt Ihnen, auf "jeden Kindprozess" zu warten. Wenn Sie das so oft machen, sollten Sie golden sein.

Wenn das fehlschlägt (nicht sicher über die Garantien), können Sie den Brute-Force-Ansatz in einer Schleife sitzt tun konnten, tut eine waitpid() mit der NOHANG Option auf jedem Ihres Kind PIDs, und dann eine Zeit lang zu verzögern, bevor Sie es wieder.

+0

Bitte beachten Sie den Code, ich habe genau das gleiche getan, was Sie sagen. – avd

+0

@aditya: Äh, nein, mein Vorschlag bedeutet zu tun, wie Jborque vorschlägt, ich habe nichts über die Verwendung eines Signal-Handlers gesagt. – unwind

Verwandte Themen