1.问题来源
大家都知道,子进程在终止之后,会使得内核产生SIGCHLD信号递送给父进程
此时我们在网络编程中必须做到的(以下来自unix网络编程卷1)
(1)当fork子进程时,必须捕获SIGCHLD信号
(2)当捕获信号时,必须处理被中断的系统调用
(3)SIGCHLD的信号处理函数必须被正确编写,使用waitpid函数以免使得留下僵尸进程
看到上述资料时,我就在想,什么是僵尸进程呢?
2.什么是僵尸进程
于是有了接下来这段话
一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
那么我又产生了问题,内核开发人员是不是闲得慌,子进程exit()后直接销毁不就好了,为什么还要为进程设置一种僵尸状态(TASK_ZOMBIE)?
答案: 给进程设置僵尸状态的目的是维护子进程的信息,以便父进程在以后某个时间获取。这些信息包括子进程的进程ID、终止状态以及资源利用信息(CPU时间,内存使用量等等)。如果一个进程终止,而该进程有子进程处于僵尸状态,那么它的所有僵尸子进程的父进程ID将被重置为1(init进程)。继承这些子进程的init进程将清理它们(init进程将wait它们,从而去除僵尸状态)。
3.具体实例
“给进程设置僵尸状态的目的是维护子进程的信息,以便父进程在以后某个时间获取”这句话的具体实例:
比如:进程创建一个子进程来执行特定的任务,当子进程终止时,父进程捕获SIGCHLD信号来知道子进程已经终止,但这个任务到底有没有完成,如果我们不对子进程维护一些必要信息的话,就无从知晓,故内核开发人员设计了一种僵尸状态(其中维护了子进程id,子进程终止状态、资源利用信息等)来等待父进程的青睐,父进程得到想要的信息之后再告诉内核你可以回收子进程的id及其残余信息,子进程得以真正的销毁了。
注意,僵尸进程也是一种进程,其还是会占用pid,而pid是一种很珍贵的资源,如果父进程不能及时调用wait类函数处理,其会一直占用,最终可能导致我们耗尽进程资源