摩诃般若波罗蜜全文:僵尸进程的产生过程模拟

来源:百度文库 编辑:中财网 时间:2024/05/09 02:55:56

在上篇文章中我提到了僵尸进程,本篇中就来模拟一下僵尸进程是如何产生的。

请看下面这段代码:

#include 
#include
 
int main()
{
int pid = fork();
if ( pid > 0 )
{
while ( 1 )
{
sleep(3);
}
}
else if ( pid == 0 )
{
printf("i die\n");
}
}

上述程序中,fork了一个子进程,并且子进程很快就退出。父进程持续进行sleep,这样子进程就变成了僵尸进程。利用ps命令可以清晰的看到这一点。

[leconte@localhost ~]$ ps axu | grep test
leconte 32600 0.0 0.0 1516 268 pts/1 S+ 20:43 0:00 ./test
leconte 32601 0.0 0.0 0 0 pts/1 Z+ 20:43 0:00 [test]
leconte 32603 0.0 0.1 5024 668 pts/2 R+ 20:43 0:00 grep test

Z+代表进程32601是僵尸进程。

僵尸进程和孤儿进程的区别是,孤儿进程是子进程还在运行,而父进程挂了,子进程被init进程收养。僵尸进程是父进程还在运行但是子进程挂了,但是父进程却没有使用wait来清理子进程的进程信息,导致子进程虽然运行实体已经消失,但是仍然在内核的进程表中占据一条记录,这样长期下去对于系统资源是一个浪费。

这时候杀掉父进程即可清理该僵尸进程。当然这并非长久之计,根本的办法是从代码上进行控制,防止类似的事情再发生。常见的方法无非是处理父进程的SIGCHLD信号,在信号处理函数里用wait或者waitpid等函数进行处理。更改后的代码如下:

#include 
#include
#include
 
void* handler(int sig)
{
int status;
 
if (waitpid(-1, &status, WNOHANG) >= 0)
{
printf("child is die,i know\n");
}
}
 
int main()
{
signal(SIGCHLD,handler);
int pid = fork();
if ( pid > 0 )
{
while ( 1 )
{
sleep(3);
}
}
else if ( pid == 0 )
{
printf("i die\n");
}
}

这样更改后执行的输出如下:

[leconte@localhost test]$ ./test
i die
child is die,i know

可见父进程已经成功地处理了子进程的退出信号,子进程彻彻底底的消失了。