2013-04-18 15 views
10

Wikipedia mówi: "Proces potomny, który kończy się, ale nigdy nie jest oczekiwany przez jego rodzica, staje się procesem zombie". Uruchomę ten program:Dlaczego istnieją procesy zombie?

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
int main() 
{ 
    pid_t pid, ppid; 
    printf("Hello World1\n"); 
    pid=fork(); 
    if(pid==0) 
    { 
     exit(0);  
    } 
    else 
    { 
     while(1) 
     { 
     printf("I am the parent\n"); 
     printf("The PID of parent is %d\n",getpid()); 
     printf("The PID of parent of parent is %d\n",getppid());   
     sleep(2); 
     } 
    } 
} 

To tworzy proces zombie, ale nie mogę zrozumieć, dlaczego proces zombie jest tutaj tworzony?

Wyjście programu jest

Hello World1 
I am the parent 
The PID of parent is 3267 
The PID of parent of parent is 2456 
I am the parent 
The PID of parent is 3267 
The PID of parent of parent is 2456 
I am the parent 
.... 
..... 

Ale dlaczego jest tak, że „proces dziecko kończy, ale nie czekał na jego rodzica” w tym przypadku?

+0

Pytasz dlaczego pojęcie proces zombie został wprowadzony w Unix? W tej chwili jedyną odpowiedzią na twoje pytanie, które widzę, jest "ponieważ tak zdefiniowano procesy zombie". –

+0

** "nie można zrozumieć, dlaczego proces zombie jest tutaj tworzony" ** To dlatego, że nie wywołujesz 'wait()', aby odczytać status wyjścia dziecka, i dlatego jego wpis został pozostawiony w tabeli procesu . –

+0

To jest w porządku. Ale kiedy dziecko biegnie przez jakiś czas i istnieje nie ma żadnego zombie – user567879

Odpowiedz

25

W kodzie, zombie jest tworzony na exit(0) (komentarz ze strzałką poniżej):

pid=fork(); 
if (pid==0) { 
    exit(0); // <--- zombie is created on here 
} else { 
    // some parent code ... 
} 

Dlaczego? Ponieważ nigdy nie robiłeś tego. Gdy coś wywołuje waitpid(pid), zwraca on po śmierci informacje o procesie, takie jak kod zakończenia. Niestety, gdy proces zakończył się, jądro nie może po prostu usunąć tego wpisu procesu, lub kod powrotu zostanie utracony. Więc czeka na kogoś na wait na nim i pozostawia ten wpis procesu, nawet jeśli tak naprawdę nie zajmuje żadnej pamięci poza wejściem do tabeli procesu - to jest dokładnie to, co nazywa się zombie.

Masz kilka opcji, aby uniknąć tworzenia zombie:

  1. Dodaj waitpid() gdzieś w procesie macierzystym. Na przykład, robi to pomoże:

    pid=fork(); 
    if (pid==0) { 
        exit(0);  
    } else { 
        waitpid(pid); // <--- this call reaps zombie 
        // some parent code ... 
    } 
    
  2. wykonać dwukrotnie fork() uzyskanie wnuka i zjazd na dziecko podczas wnuczek jest wciąż żywa. Wnuki będą automatycznie adoptowane przez init, jeśli ich rodzic (nasze dziecko) umrze, co oznacza, że ​​jeśli umrze wnuk, zostanie on automatycznie zmieniony na wait przez init. Innymi słowy, trzeba zrobić coś takiego:

    pid=fork(); 
    if (pid==0) { 
        // child 
        if (fork()==0) { 
         // grandchild 
         sleep(1); // sleep a bit to let child die first 
         exit(0); // grandchild exits, no zombie (adopted by init) 
        } 
        exit(0);  // child dies first 
    } else { 
        waitpid(pid); // still need to wait on child to avoid it zombified 
        // some parent code ... 
    } 
    
  3. jawnie ignoruje sygnał SIGCHLD w rodzica. Gdy dziecko umiera, rodzic otrzymuje sygnał, który pozwala mu reagować na śmierć dzieci. Po otrzymaniu tego sygnału możesz zadzwonić pod numer waitpid() lub zainstalować program obsługi sygnału ignorującego (używając signal() lub sigaction()), który sprawi, że dziecko nie stanie się zombie. Innymi słowy, coś takiego:

    signal(SIGCHLD, SIG_IGN); // <-- ignore child fate, don't let it become zombie 
    pid=fork(); 
    if (pid==0) { 
        exit(0); // <--- zombie should NOT be created here 
    } else { 
        // some parent code ... 
    } 
    
+2

Dlaczego ignorowanie sygnału SIGCHLD zabija zombie? Rozumiem, że zapewnia to, że proces potomny nie stanie się zombie. Czy proces nie-zombie zakończy się po zakończeniu programu? A proces zombie nie zakończy się po zakończeniu programu? – user234159

+3

Znowu, zombie nie może zostać zabite: jego już martwy, wszystko, co pozostaje, to wpis w tabeli procesów jądra. Ignorowanie SIGCHLD pozwala jądrze wiedzieć, że można go natychmiast usunąć. – mvp

Powiązane problemy