目录
僵尸进程概念
在一个进程处于终止状态后,与其相关的信息(如pid)仍然存在,没有被释放完全。即该进程无法再次复苏,但却占用一定资源。
为什么存在僵尸进程?
由于子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 那么会不会因为父进程太忙来不及wait子进程,或者说不知道 子进程什么时候结束,而丢失子进程结束时的状态信息呢? 不会。因为UNⅨ提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是: 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等),这些信息仍然被保存在PCB(进程控制块)中,直到父进程通过wait / waitpid来取时才释放。
危害
大量僵尸进程将占用系统内核、空间内存资源,如果进程表被填满,系统将不能再产生新进程。
解决方法
被动处理方法:
如果僵尸进程的父进程已终止,那该僵尸进程将有init进程收养,并调用wait函数将其销毁。
主动处理方法
⒈父进程通过wait()和waitpid()等函数等待子进程结束,这会导致父进程挂起。
(164条消息) Linux中wait()函数_DNFK的博客-CSDN博客_wait函数
wait()函数功能是:父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
【转】linux : waitpid函数 - wi100sh - 博客园 (cnblogs.com)
waitpid()函数的功能是:挂起当前进程的执行,直到指定的子进程状态发生变化。(挂起和阻塞行为类似)(注意,这是博主从别的博客看到的描述,很有可能别处把挂起和阻塞这俩名词混用了)
(164条消息) 阻塞与挂起的区别_么滴感情de杀手的博客-CSDN博客_挂起和阻塞的区别
⒉ 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后, 父进程会收到该信号,可以在handler中调用wait回收。
⒊ 如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD,SIG_IGN) 通知x系统内核,自己对子进程的结束信息与状态不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号。
⒋ 还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一 个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收 还要自己做。(将一定的活放入孙进程)