僵尸进程

1.僵尸进程与孤儿进程

  • 僵尸进程:如果子进程先于父进程退出,此时子进程便成为一个尸体;此前,如果父进程没有调用wait等相关系统调用,那么子进程便成为僵尸进程.

  • 孤儿进程:如果父进程先于子进程退出,那么子进程变成为孤儿进程,将被init进程领养.

2.进程相关数据结构

  • 进程控制块PCB:保留了进程运转时所需要的全部信息,是进程表中的一个entry.

当以fork()系统调用建立一个新的进程后,核心进程就会在进程表中给这个新进程分配一个PCB,然后将相关信息存储在该进入点所对应的进程表内。这些信息中有一项是其父进程的识别码。当这个进程走完了自己的生命周期后,它会执行exit()系统调用,此时原来进 程表中的数据会被该进程的退出码(exit code)、执行时所用的CPU时间等数据所取代,这些数据会一直保留到系统将它传递给它的父进程为止。由此可见,defunct进程的出现时间是在子进 程终止后,但是父进程尚未读取这些数据之前。

3.linux中的进程操作命令

我们主要来讲解ps\pgrep\pkill三个命令

  • ps:report a snapshot of the current processes.

To see every process on the system using standard syntax:
ps -ef

  1 UID        PID  PPID  C STIME TTY          TIME CMD                                                                                               
  2 root         1     0  0 Mar09 ?        00:00:01 /sbin/init

To see every process on the system using BSD syntax:
ps aux

1 USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
2 root         1  0.0  0.0  24588  2364 ?        Ss   Mar09   0:01 /sbin/init

pgrep和pkill不详细解释了.需要注意的是,上述三个命令得到的都是PCB中的信息.对于僵尸进程,
仍然存在PCB,所以这类进程虽然已经停止,但是用pgrep仍然可以找到,而且无法用pkill杀死.

4.如何杀死僵尸进程

其实用”杀死”已经不是很严密了,因为僵尸进程已经”死了”.准确说是清除僵尸进程的PCB. 由于kill和pkill命令是通过给进程发送信号来让进程退出的,而僵尸进程产生的原因: 父进程没有wait子进程结束也没有安装信号处理函数,况且进程”已经死了”,所以也无法接受信号.

我们用另外一种方法来彻底清除僵尸进程: 杀死僵尸进程的父进程,从而让僵尸进程被init进程接管.

ps -ef | grep defunct_process_pid | xargs pkill

5.如何避免产生僵尸进程

1.设置SIGCLD信号为SIG_IGN,系统将不产生僵死进程。
2.用两次fork(),而且使紧跟的子进程直接退出,使得孙子进程成为孤儿进程,从而init进程将负责清除这个孤儿进程。

那么问题来了:Q1:信号的作用原理是什么?
Q2:init进程是如何负责清除孤儿进程的?方法2中的子进程怎么办?为何不直接一次fork,然后调用wait系统调用?

关于这些疑问,我们可以参考系列文章:
linux信号原理
init进程的作用与工作原理
wait系统调用

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。