僵尸进程产生的原因是父进程没有处理子进程的退出信息,导致子进程退出后因zombie结构没有及时释放而变成了僵尸进程,为避免该问题的产生,建议采用fork两次的方案。
进程关系为:爷爷->父亲->孙子。
方案分析:
之所以会产生僵尸进程,是因为在进程后终止,除了回收分配到的内存和资源外,还要保留一部分信息供感兴趣者使用,一般是父进程。但是,如果在子进程退出后,父进程没有处理子进程发出的用于处理退出信息的SIGCHLD信号,则会导致子进程一直处于EXIT_ZOMBIE状态而成为僵尸进程。
进程的僵尸状态生命周期为:进程终止到父进程调用waitpid处理SIGCHLD信号。
采用fork两次的方式,由爷爷产生父亲,父亲产生孙子,并且父亲进程在产生孙子以后就退出,这会导致孙子进程被祖宗进程init收养,而init进程是一定会处理进城的退出信息的,这就避免了孙子进程变为僵尸进程。
实例代码:
/*fork两次避免孙子变成僵尸*/
int double_fork_no_zomble()
{
pid_t grandpa;
pid_t father;
pid_t child;
father = fork();
/*进入父进程处理流程*/
if (father == 0)
{
child = fork();
/*fork出错*/
if (child < 0)
{
perror("father fork:");
exit(-2);
}
/*父进程退出*/
else if (child > 0)
{
printf("father normal exit\n");
exit(0);
}
/*孙子进程执行任务*/
else
{
do_something_child();
}
}
else if (father < 0)
{
perror("grandpa fork:");
exit(-1);
}
return 0;
}