为什么僵尸进程存在?

维基百科说:“一个终止但永远不会被父母等待的儿童stream程变成了一个僵尸stream程。” 我运行这个程序:

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

这会创build一个僵尸进程,但我不明白为什么在这里创build一个僵尸进程?

该程序的输出是

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

但为什么在这种情况下,“subprocess终止,而不是由其父母等待”呢?

Solutions Collecting From Web of "为什么僵尸进程存在?"

在你的代码中,僵尸是在exit(0)上创建的(注释如下箭头):

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

为什么? 因为你永远不会wait 。 当某些事情调用waitpid(pid) ,它会返回关于进程的postmortem信息,如退出代码。 不幸的是,当进程退出时,内核不能仅仅处理这个进程入口,否则返回代码将会丢失。 所以它等待有人wait它,即使它没有真正占用除了进程表中的内存之外的任何内存,也留下了这个进程条目 – 这正是所谓的僵尸

你有几个选择来避免创建僵尸:

  1. 在父进程的某处添加waitpid() 。 例如,这样做将有助于:

     pid=fork(); if (pid==0) { exit(0); } else { waitpid(pid); // <--- this call reaps zombie // some parent code ... } 
  2. 当孙子还活着的时候, 执行双fork()来获取孙子,并在子孙中退出。 如果他们的父母(我们的孩子)死了,孙子们会被init自动采纳,这意味着如果孙子死了,它会被init自动wait 。 换句话说,你需要做这样的事情:

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