2013-04-18 15 views
10

ウィキペディアは「終了するが、その親によって待たれることのない子プロセスはゾンビプロセスになる」と述べている。なぜゾンビプロセスが存在するのですか?

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

あるしかし、なぜそれが「子プロセスが終了するが、その親によってで待っていない」ということである。この場合には?

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

なぜ:あなたのコードで

+0

を求めていますか?それが立っているように、あなたの質問に対する唯一の答えは、「ゾンビのプロセスがどのように定義されているのか」ということです。 –

+0

** "ここでゾンビプロセスが作成された理由を理解できませんでした" ** これは、子プロセスの終了ステータスを読み取るために 'wait()'を呼び出さないため、そのエントリがプロセステーブルに残っているためです。 –

+0

それは大丈夫です。しかし、子供がしばらく走り回ってゾンビがいない場合、 – user567879

答えて

25

は、ゾンビは、exit(0)(下の矢印付きのコメント)上で作成されましたか?あなたは決して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によって採用されます。つまり、孫が死亡すると自動的にwaitinitになります。

    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()を使用)をインストールして、子供がゾンビにならないようにすることもできます。言い換えれば、このような何か:ゾンビプロセスの概念はUNIXで導入されたなぜあなたは

    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

関連する問題