首先介绍一下什么是僵死进程
int main()
{
int n = 0;
char *s = NULL;
pid_t pid = fork();
assert(pid != -1);
if(pid == 0)
{
n = 3;
int i = 0;
for(; i < n; i++)
{
sleep(1);
printf("child running\n");
}
}
else
{
n = 7;
int i = 0;
for(; i < n; i++)
{
sleep(1);
printf("parent running\n");
}
}
}
此时程序运行后,在子程序结束后,父进程尚且没有完成,此时查看一下进程信息,可以得到
可以看到两个signalttt进程,其中子程序的signalttt进程已经处于defunct状态,此时子进程已经代码执行完毕,但是这个进程并没有终止,这就对CPU的进程资源造成了很多的浪费,如果说短时间内产成了大量的僵死进程,那么此时因为进程号等信息占用,此时不能创建新的进程
为什么会出现僵死进程呢?
我们来改一下代码:
int main()
{
int n = 0;
char *s = NULL;
if(pid == 0)
{
n = 7;
int i = 0;
for(; i < n; i++)
{
sleep(1);
printf("child running\n");
}
}
else
{
n = 3;
int i = 0;
for(; i < n; i++)
{
sleep(1);
printf("parent running\n");
}
}
}
再次在运行途中查看ps
此时并没有和之前一样出现僵死进程,而我们仅仅是将子进程改的运行的时间比父进程长了一些,然后再次查看时候,发现僵死进程就消失了???
所以我们可以得到条件,僵死进程中,父进程一定要“活得久”~
这里本质上是因为,在Linux系统中,进程是有父子关系的,从init进程开始展开,是一个大的进程树,而子进程的结束都会由子进程向它的父进程发送一个信号(SIGCHLD),而此时如果父进程在运行中没有获取子进程的退出码,这样就出现了僵死进程
关于僵死进程的处理
在Linux系统中有一个特殊的处理方法,
signal(SIGCHLD,SIG_IGN);
子进程在结束时候会向父进程发送一个子进程结束的信号,我们调用signal函数去忽略掉这个信号,那么这时候子进程就会变成了孤儿进程,会自动的被init接收处理,init进程会在进程表中挨个查找孤儿进程,也就是说,进程表越大那么这个过程造成的资源占用也就越多也可以在父进程中用
wait();
函数,这样在执行到这句时,父进程会等待到子进程结束后,但是这句会造成父进程的挂起同样的,也可以用
signal(SIGCHLD,fun);
去实现一个处理子进程信号的函数,让父进程接收到信号之后,调用wait()
将子进程结束掉还有一种特殊的是利用两次
fork()
,这样父进程在第一次创建的子进程1中,再次创建一个子进程2,子进程2负责执行子进程的工作,而子进程1只做一件事件--------wait(子进程2);专心致志等待子进程2结束,这样就处理了wait导致的进程挂起的问题
`
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。