前言
最近接触了僵尸进程这个概念,在被同学问到僵尸进程的产生、避免、危害时感觉还是概念模糊,没有深入了解,现在做了一些整理来复习僵尸进程的相关知识。
僵尸进程是什么?
在Linux下进程状态由五种,僵死状态就是一种特殊的进程状态,它放弃了几乎所有的内存地址空间,也没有任何的可执行的代码,也不被调度器再次调度,它仅仅是在进程列表中保留一个位置,在这个位置中记载了该进程的进程状态。
Linux下的僵尸进程(Zombie) 和影视剧中的僵尸类似:僵尸进程就是处于僵死状态的进程(进程已经退出,但资源并没有完全被释放)
。
僵尸进程是如何产生的?
子进程先于父进程退出
由于要保存自身的退出返回值,资源并没有完全被释放
此时操作系统通知父进程获取子进程的退出状态并允许操作系统释放资源
但父进程默认忽略子进程退出时发送给父进程的SIGCHLD信号
所以父进程并没有注意到子进程的退出状态
导致子进程退出但资源并没有完全被释放处于僵死状态导致了僵尸进程的出现
- 下面用代码简单的实现一下僵尸进程:
命令ps aux | grep -w ‘Z’ 可以看到进程3453是一个僵尸进程
注: 僵尸进程不能用 kill 命令杀死
简单处理: 退出父进程,僵尸子进程变为孤儿进程,由init进程收养释放资源。
僵尸进程有哪些危害?
僵尸进程处于僵死状态,资源并没有完全被释放(进程的ID号、进程的退出状态、进程运行的CPU时间等)
可能会导致资源泄露的问题
并且由于操作系统所能创建的最大进程数量是有限的(进程号被大量占用)会导致新的进程无法创建
僵尸进程该如何避免?
既然僵尸进程可能导致这么严重的问题出现,那么避免僵尸进程的出现就有着重要的意义,我们下面讨论一下如何避免僵尸进程的出现。
- 方法一:进程等待
进程等待就是父进程调用wait/waitpid函数等待子进程的退出
获取子进程的退出返回值并释放子进程的资源
避免僵尸进程的出现
父进程创建子进程之后,子进程sleep5秒后退出,父进程sleep20秒再调用wait函数处理僵尸进程,这时子进程成为15秒的僵尸进程后,进程等待获取子进程的退出返回值,释放子进程的资源。
- 方法二:处理SIGCHID信号
采用SIGCHLD信号通知处理机制
父进程注册一个信号处理函数signal(SIGCHLD, sig_child)
然后每当子进程退出的时候父进程都会收到SIGCHLD信号
触发sig_child函数,调用waitpid函数等待子进程的退出
运行结果:打断父进程的阻塞 去处理SIGCHLD信号
小结
通过上面的学习,我们对僵尸进程的概念、产生、危害、避免都有了一定的认识,知己知彼才能百战百胜,在今后的学习当中,在我们遇到僵尸进程带来的问题时,我们就能很好的去处理这些麻烦了。