维基百科说:“一个终止但从未被其父级等待的子进程变成了僵尸进程。” 我运行此程序:
#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 .... .....
但是在这种情况下,为什么“子进程终止但没有被其父进程等待”呢?
在您的代码中,创建了僵尸exit(0)(带有以下箭头的注释):
exit(0)
pid=fork(); if (pid==0) { exit(0); // <--- zombie is created on here } else { // some parent code ... }
为什么?因为你从来没有wait上过。调用时waitpid(pid),它将返回有关进程的事后信息,例如其退出代码。不幸的是,当进程退出时,内核不能仅仅丢弃该进程条目,否则返回代码将丢失。因此,它等待有人wait在上面等待,并留下该进程条目,即使除了进程表中的条目之外,它实际上并没有占用任何内存- 这就是所谓的 zombie 。
wait
waitpid(pid)
您几乎没有选择来避免创建僵尸:
waitpid()
pid=fork(); if (pid==0) { exit(0); } else { waitpid(pid); // <--- this call reaps zombie // some parent code ... }
fork()
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 ... }
SIGCHLD
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 ... }