2013-04-18 2 views
10

Wikipedia говорит, что «дочерний процесс, который заканчивается, но его никогда не ждет, его родитель становится процессом зомби». Я запускаю эту программу:Почему зомби-процессы существуют?

#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); 
     } 
    } 
} 

Это создает процесс зомби, но я не могу понять, почему здесь создается зомби-процесс?

Выход программы

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 
.... 
..... 

Но почему это, что «дочерний процесс завершается, но не прислуживал своим родителем» в данном случае?

+0

Вы спрашиваете, почему понятие процесса зомби был введен в Unix? Как бы то ни было, единственный ответ на ваш вопрос, который я вижу, «потому что так определяются процессы зомби». –

+0

** «не мог понять, почему здесь создается зомби-процесс» ** Это было бы потому, что вы не вызываете 'wait()' для чтения статуса выхода ребенка, и, следовательно, его запись оставлена ​​в таблице процессов , –

+0

Это нормально. Но когда ребенок бежит в течение некоторого времени и существует, там нет никакого зомби – user567879

ответ

25

В своем коде, зомби создается на exit(0) (комментарий со стрелкой внизу):

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

Почему? Потому что вы никогда не делали wait. Когда что-то вызывает waitpid(pid), он возвращает посмертную информацию о процессе, например, код выхода. К сожалению, когда процесс завершен, ядро ​​не может просто избавиться от этой записи процесса, иначе код возврата будет потерян. Таким образом, он ждет кого-то до wait на нем и оставляет эту запись процесса, даже если она действительно не занимает никакой памяти, кроме входа в таблицу процессов - это именно то, что называется зомби.

У вас есть несколько вариантов, чтобы избежать создания зомби:

  1. Добавить waitpid() где-то в родительском процессе. Например, делать это поможет:

    pid=fork(); 
    if (pid==0) { 
        exit(0);  
    } else { 
        waitpid(pid); // <--- this call reaps zombie 
        // some parent code ... 
    } 
    
  2. Выполните двойные fork() получить внучку и выход в ребенке, а внук еще жив. Внуки будут автоматически приняты init, если их родитель (наш ребенок) умрет, что означает, что если внук умрет, он автоматически будет wait ed на init. Другими словами, вам нужно сделать что-то вроде этого:

    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. Явное игнорировать сигнал SIGCHLD в родительских. Когда ребенок умирает, родитель получает сигнал SIGCHLD, который позволяет ему реагировать на смерть детей. Вы можете позвонить waitpid() после получения этого сигнала или установить явный обработчик сигнала игнорирования (используя signal() или sigaction()), который будет следить за тем, чтобы ребенок не стал зомби. Другими словами, что-то вроде этого:

    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

Почему игнорирование сигнала SIGCHLD убивает зомби? Я понимаю, что он гарантирует, что детский процесс не станет зомби. Таким образом, процесс не-зомби прекратится после выхода программы? И процесс зомби не будет прекращаться после выхода программы? – user234159

+3

Опять же, зомби нельзя убить: его уже мертвый, все, что осталось, - это запись в таблицу процессов ядра. Игнорирование SIGCHLD позволяет ядру знать, что это нормально, чтобы немедленно удалить эту запись. – mvp

Смежные вопросы