僵尸进程:如果子进程先于父进程退出,此时子进程便成为一个尸体;此前,如果父进程没有调用wait等相关系统调用,那么子进程便成为僵尸进程.
孤儿进程:如果父进程先于子进程退出,那么子进程变成为孤儿进程,将被init进程领养.
当以fork()系统调用建立一个新的进程后,核心进程就会在进程表中给这个新进程分配一个PCB,然后将相关信息存储在该进入点所对应的进程表内。这些信息中有一项是其父进程的识别码。当这个进程走完了自己的生命周期后,它会执行exit()系统调用,此时原来进 程表中的数据会被该进程的退出码(exit code)、执行时所用的CPU时间等数据所取代,这些数据会一直保留到系统将它传递给它的父进程为止。由此可见,defunct进程的出现时间是在子进 程终止后,但是父进程尚未读取这些数据之前。
我们主要来讲解ps\pgrep\pkill三个命令
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杀死.
其实用”杀死”已经不是很严密了,因为僵尸进程已经”死了”.准确说是清除僵尸进程的PCB. 由于kill和pkill命令是通过给进程发送信号来让进程退出的,而僵尸进程产生的原因: 父进程没有wait子进程结束也没有安装信号处理函数,况且进程”已经死了”,所以也无法接受信号.
我们用另外一种方法来彻底清除僵尸进程: 杀死僵尸进程的父进程,从而让僵尸进程被init进程接管.
ps -ef | grep defunct_process_pid | xargs pkill
1.设置SIGCLD信号为SIG_IGN,系统将不产生僵死进程。
2.用两次fork(),而且使紧跟的子进程直接退出,使得孙子进程成为孤儿进程,从而init进程将负责清除这个孤儿进程。
那么问题来了:Q1:信号的作用原理是什么?
Q2:init进程是如何负责清除孤儿进程的?方法2中的子进程怎么办?为何不直接一次fork,然后调用wait系统调用?
关于这些疑问,我们可以参考系列文章:
linux信号原理
init进程的作用与工作原理
wait系统调用
原文地址:http://blog.csdn.net/trochiluses/article/details/44257359