2010-05-19 15 views
7

Wenn ich einen untergeordneten Prozess fork bin und der untergeordnete Prozess beendet wird, bevor der übergeordnete Benutzer waitpid aufruft, ist die Exit-Statusinformation, die von waitpid festgelegt wurde, noch gültig? Wenn ja, wann wird es ungültig? Wie kann ich sicherstellen, dass ich waitpid auf der Child-PID aufrufen kann und nach einer beliebigen Zeit noch gültige Exit-Statusinformationen abrufen kann, und wie kann ich "aufräumen" (dem Betriebssystem mitteilen, dass ich nicht mehr an der Statusinformationen für den fertigen Kindprozess beenden)?Liefert waitpid gültige Statusinformationen für einen untergeordneten Prozess, der bereits beendet wurde?

Ich spielte mit dem folgenden Code, und es scheint, dass die Exit-Statusinformationen für ein paar Sekunden gültig sind, nachdem das Kind fertig ist, aber ich weiß nicht, wie lange oder wie ich das Betriebssystem informieren soll wird waitpid nicht wieder anrufen:

#include <assert.h> 
#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 

int main() 
{ 
    pid_t pid = fork(); 

    if (pid < 0) { 
     fprintf(stderr, "Failed to fork\n"); 
     return EXIT_FAILURE; 
    } 
    else if (pid == 0) { // code for child process 
     _exit(17); 
    } 
    else { // code for parent 
     sleep(3); 

     int status; 
     waitpid(pid, &status, 0); 
     waitpid(pid, &status, 0); // call `waitpid` again just to see if the first call had an effect 
     assert(WIFEXITED(status)); 
     assert(WEXITSTATUS(status) == 17); 
    } 

    return EXIT_SUCCESS; 
} 

Antwort

10

Ja, waitpid funktionieren wird, nachdem das Kind verlassen hat. Das Betriebssystem behält den Eintrag eines untergeordneten Prozesses in der Prozesstabelle (einschließlich Exit-Status) bei, bis der übergeordnete Benutzer waitpid (oder eine andere wait -Familienfunktion) aufruft oder bis der übergeordnete Prozess beendet wird (zu diesem Zeitpunkt wird der Status vom init-Prozess erfasst) . Das ist ein "Zombie" -Prozess: Ein Prozess, von dem ein "Zombie" -Prozess ausgeführt wurde, befindet sich für genau diesen Zweck immer noch in der Prozesstabelle.

Der Eintrag des Prozesses in der Tabelle sollte nach dem ersten Aufruf von waitpid gelöscht werden. Ich vermute, der Grund, dass Sie in Ihrem Beispiel waitpid zweimal aufrufen können, ist einfach, weil waitpid das Argument status nicht ändert, wenn pid nicht mehr existiert. Der erste Anruf sollte also funktionieren und status ausfüllen, und der zweite Anruf sollte einen Fehlercode zurückgeben und status nicht ändern. Sie können dies überprüfen, indem Sie die Rückgabewerte der Aufrufe waitpid überprüfen und/oder zwei verschiedene status Variablen verwenden.

+0

Tatsächlich war der zweite 'waitpid' Aufruf fehlgeschlagen. Daran habe ich nicht gedacht! Vielen Dank, dass Sie darauf hingewiesen haben. –

3

Das Betriebssystem hält beendet Prozess in einem zombie state, bis seine Eltern (die die init sein könnten, wenn der ursprüngliche Eltern-Prozess vorzeitig beendet) sammelt, dass die Exit-Status mit wait(2) Systemaufruf. Die Antwort ist also - der Exit-Status des Prozesses wird nicht ungültig.

2

Ja.

Vom man page:

Ein Kind, das endet, hat aber nicht wartet für einen "Zombie" wird. Der Kernel verwaltet einen minimalen Satz von Informationen über den Zombie-Prozess (PID, Beendigungsstatus, Ressourcen Nutzungsinformationen), um die Eltern, damit später eine Wartezeit zu Informationen über das Kind erhält zuführen.