僵尸进程:
- 僵尸状态是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程的返回代码就会产生僵死(尸)进程
- 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取状态代码。
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程就会进入Z状态。
模拟僵尸进程也比较简单,只是要求子进程退出,而父进程还在执行,并且父进程没有读取子进程退出状态码。下面我们来模拟一个僵尸进程
代码:
在一个终端运行上图所示代码
接下来打开另外一个终端,执行下面这条指令:(执行这条指令时,速度要快一点,因为我们的代码值sleep了5秒,当然你也可以设置时间长一点)
while :; do ps aux | grep myproc | grep -v grep; sleep 1;echo "########################"; done
接下来你会看到下图所示的现象:
分析一下这张图所代表的状态:
上图中前面四个红色小框内代表子进程的状态是S,后面三个红色小框表示子进程已经进入了僵尸状态,想必大家都知道子进程会进入僵尸状态的原因吧:当子进程sleep(5)结束后,立即执行exit函数,子进程退出;而父进程一直在while(1)死循环,无法读取子进程的退出状态,导致子进程变成了僵尸进程。
僵尸进程的危害:
如果父进程不调用wait/waitpid,则子进程的保留信息不会被释放,造成内核资源的无法回收,也就是会造成内存泄露;
同时进程号会一直被占用,系统所能使用的进程号是有限的,大量地产生僵尸进程将会导致系统不能产生新的进程。
孤儿进程:
- 父进程如果提前退出,子进程就称之为“孤儿进程”
- 孤儿进程被1号init进程领养,当然也是由init进程回收
- 1号进程可以约等于系统
实现孤儿进程也很简单,只需要让父进程退出,子进程在执行就OK了,我们可以对僵尸进程的代码稍作修改就可以看到孤儿进程了
运行上图所示代码:
接下来同样的打开另外一个终端,执行下面这条指令:(执行这条指令时,速度要快一点,因为我们的代码值sleep了5秒,当然你也可以设置时间长一点)
while :; do ps axj | grep myproc | grep -v grep; sleep 1;echo "########################"; done
注意此时的参数是 axj 而不是 aux,因为axj才能看到父进程的id。我们可以看到下图所示的现象:
分析:
上图中前面四个红色小框内代表子进程的父进程的id是3259,后面六个红色小框表示子进程的父进程id是1,当父进程sleep(5)结束后,立即执行exit函数,父进程退出;而子进程一直在while(1)死循环,子进程的父进程变成1号init进程,由1号进程回收。