2017-05-17 2 views
2

Aus Lerngründen habe ich einen Code geschrieben, um Zombie-Prozesse zu generieren. Hier ist der Code:Ein Child-Prozess, der Exit() aufruft, aber kein Zombie wird

#include <sys/types.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

pid_t pid; 

int main() { 
    pid = fork(); 
    if (pid == 0) { 
    exit(0); 
    } else { 
    printf("the child process is %d", pid); 
    sleep(20); 
    } 
} 

In meiner Annahme, die Codes oben sollte in einer solchen Art und Weise verhalten: das Kind Prozess erhalten pid von 0 und exit mit dem Statuscode 0; Der übergeordnete Prozess erhält pid des untergeordneten Prozesses und wird ausgedruckt und für 20 Sekunden in den Ruhezustand versetzt. Da der übergeordnete Prozess wait nicht aufruft, wenn der untergeordnete Prozess ist, sollte der untergeordnete Prozess etwa 20 Sekunden lang Zombie sein.

Wenn ich jedoch die Codes ausführe, wartet es ungefähr 20 Sekunden und druckt die PID des Kindprozesses aus. In den 20 Sekunden erscheint der Kindprozess nicht in ps -l als Zombie-Prozess.

Kann mir jemand sagen, was den Unterschied zwischen meinem Verständnis der Codes und ihrem tatsächlichen Verhalten ausmacht?

P.S. Ich benutze Mac OS Sierra.

+2

Versuchen Sie, eine neue Zeile "\ n" zu Ihrem Druck hinzuzufügen ... stdout ist gepuffert. – technosaurus

+0

Hinzufügen von "\ n" hilft, die Nachricht auszudrucken, danke! Der Kindprozess wird jedoch immer noch kein Zombie. – Musen

Antwort

-1

Was meinen Sie "der Kindprozess erscheint nicht in ps -l als Zombie-Prozess"? Welchen Zustand siehst du stattdessen? Oder meinst du vielleicht, du siehst das Kind überhaupt nicht? Um klar zu sein, können Sie den Prozess überprüfen, indem Sie "ps 1234" (oder was auch immer Sie erhalten) ausführen.

#include <sys/types.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

pid_t pid; 

Warum ist das ein globales?

int main() { 

Sollte int Haupt (void) sein.

pid = fork(); 
    if (pid == 0) { 
    exit(0); 

Sollte _exit zu vermeiden "an der Ausfahrt" Handler aufrufen. In diesem Spielzeug-Beispiel spielt das keine Rolle, aber es gibt keinen Grund, falsche Gewohnheiten zu pflegen.

} else { 
    printf("the child process is %d", pid); 
    sleep(20); 

Sie können stattdessen nur pause() oder getchar().

} 
} 
+0

Aufruf von '_exit()' ist eine gute Angewohnheit? Was? Was ist der Grund für die Installation von Exit-Handlern? Dies ist das erste Mal, dass ich das in meiner mehr als 40-jährigen Erfahrung im Programmieren höre. 8/ –

+0

In dem Kind, nicht im Allgemeinen. Und das ist, sie nicht mehrere Male zu nennen. –

+0

eine gute Angewohnheit ist etwas, was Sie immer in Ihren Programmen tun. Das Aufrufen von '_exit()' anstelle von 'exit()' ist ** nicht ** eine gute Angewohnheit. Es ist eine Idiot-Angewohnheit, so dass Sie nicht zulassen, dass Dateien geschlossen oder Status gespeichert werden. Bibliotheken nutzen es, so ist es eine gute Angewohnheit, dass Exit-Handler ausgeführt werden können. Da Sie zwei Prozesse haben, verfügen Sie über zwei Instanzen der Ausführungsumgebung aller Bibliotheken. Daher müssen die at-exit-Handler wahrscheinlich in beiden ausgeführt werden. Das Installationsprogramm eines 'atexit()' - Handlers sollte dies vor der Installation eines Handlers berücksichtigen, oder ein korrektes Dokument, wenn es nach 'fork()' aufgerufen wird, ist in Ordnung. –

0

Zwei Fragen hier. Das erste ist, dass Sie keine neue Zeile (\n) am Ende Ihrer printf Zeichenfolge haben. Da stdout zeilenweise gepuffert ist, wird die Ausgabe nicht aus dem Ausgabepuffer gelöscht, es sei denn, Sie drucken entweder einen Zeilenumbruch oder Sie löschen den Stream explizit.

So eine neue Zeile hinzufügen, und es sollte sofort drucken:

printf("the child process is %d\n", pid); 

Der Hauptgrund Sie das Kind nicht pid sehen hat damit zu tun, wie Sie den ps Befehl verwenden. Angenommen, Sie rufen ps von einer anderen Shell als die, die diesen Code ausführt, ps -l zeigt nur Prozesse aus der Sitzung, die den Befehl ausführt. Daher werden Prozesse, die von anderen Sitzungen/Shells gestartet wurden, nicht angezeigt. Wenn Sie die Option -e (d. H. ps -el oder ps -ef) verwenden, zeigt dies die vollständige Liste der Prozesse im System an. Dann sollten Sie in der Lage sein, den Zombie-Prozess zu sehen.

0

Ich habe keinen Zugriff auf ein MAC OS-System bis morgen, aber Ihr Programm erfolgreich erstellt einen Zombie-Prozess in Linux-Systemen. Ich habe Ihren Beispielcode modifiziert, um eine Nachricht hinzuzufügen, wenn der übergeordnete Prozess beendet, und die kommentierten bereits \n char richtig die Linie zu beenden und Ausgang an der Stelle des printf() Anrufs erzeugen:

zombie.c

#include <sys/types.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

pid_t pid; 

int main() { 
    pid = fork(); 
    if (pid == 0) { 
    exit(0); 
    } else { 
    printf("the child process is %d\n", pid); 
    sleep(20); 
    printf("exit();\n"); 
    } 
} 

und die Ausgabe in linux ist:

$ zombie & 
[1] 5781 
the child process is 5786 

$ ps 
    PID TTY   TIME CMD 
2569 pts/0 00:00:00 bash 
5781 pts/0 00:00:00 zombie 
5786 pts/0 00:00:00 zombie <defunct> <-- this is the zombie. 
5795 pts/0 00:00:00 ps 

$ exit(); <-- zombie program finishing. 

auf FreeBSD (und MAC OS ist sehr ähnlich) die Sache geht wie:

$ zombie & 
[1] 7326 
the child process is 7329 
$ ps 
    PID TT STAT  TIME COMMAND 
7281 0 Ss  0:00,18 -bash (bash) 
7326 0 S  0:00,02 zombie 
7329 0 Z  0:00,00 <defunct> <-- this is the zombie. 
7335 0 R+  0:00,01 ps 
$ exit(); <-- zombie program finishing. 

Morgen werde ich in der Lage sein, das gleiche in einem Mac OS X-System zu tun, und ein drittes System, das Zombie-Prozesse erstellt.

+0

Danke! Eigentlich zeigt 'ps child_id' den Zombie-Prozess an, aber es erscheint nicht, wenn ich nur' ps'. – Musen

Verwandte Themen