模拟僵尸进程和孤儿进程

僵尸进程:

  • 僵尸状态是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程的返回代码就会产生僵死(尸)进程
  • 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取状态代码。
  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程就会进入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号进程回收。

猜你喜欢

转载自blog.csdn.net/qq_41209741/article/details/82873632