僵尸进程的处理办法

2019-07-14 11:52发布

僵尸进程(僵死进程)是指一个进程主体结束,但是该进程的PCB依旧存在的情况或者在多进程编程中,父进程未结束但是子进程已经结束父进程没有对子进程进行回收。 
僵尸进程存在的意义在于进程结束后,进程的退出状态需要保存到PCB结构中,方便父进程获取子进程的退出状态。
进程真正结束的标志:1、进程主体退出。2、父进程获取子进程的退出状态之后,子进程的PCB释放。 那么我们为什么要处理掉僵尸进程呢,这是因为子进程结束完毕之后,别的空间都释放掉了,但是记录子进程的PCB还存在,长此以往,大量的PCB占用空间,就会造成空间浪费,甚至造成内存不足,所以在子进程结束后我们要将它彻底清除掉。我们可以考虑在当子进程结束时,通知父进程来处理这个结束的子进程。那么父进程是如何获取子进程的退出状态来处理该进程呢?
这就要用到wait函数来为子进程“收尸了”。
wait()的函数原型是:  
#include
#include
 
pid_t wait(int *status)     
 
   父进程一旦调用了wait函数,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait()就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。 
wait()函数的参数:
    参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,我们就可以设定这个参数为NULL,就象下面这样:
pid = wait(NULL);
    但是这个时候我们就又遇到了一个问题:如果子进程无限循环或者运行时间需要很久,那么调用wait函数,我们岂不是要浪费很大的时间,所以我们就在想,能不能同时运行父子进程,当子进程结束后以一种特定的方式通知父进程。这种方式就相当于子进程结束后给父进程发送一个信号,父进程接收到信号后停下来,来处理信号所对应的函数,处理完之后在回来继续运行,我们就可以在信号对应的函数中将子进程结束掉。
所以我们要用到SIGCHLD信号处理函数,原型为
signal(int SIGCHLD,void (*fun)(int))
可以在fun函数里实现接收到子进程结束信号后子进程的结束。即给信号绑定一个信号处理函数,当进程接收到信号后,回调信号处理函数。这样在处理僵尸进程的过程中就不用花费大量时间等待了。