最近在看APUE过程中,遇到了一个有关于进程的“僵死进程”的状态。既然遇到了进程状态的问题,索性就查了查《Linux内核设计与实现》,里面给出了5种状态,分别是“TASK_RUNNING”、“TASK_INTERRUPTIBLE”、“TASK_UNINTERRUPTIBLE”、“__TASK_STOPPED”、“__TASK_TRACED”,但这5种状态中偏偏没有“僵死”这么一个状态,这到底是怎么一回事呢?
其实这个问题很好解决。我获取有关于进程状态信息的命令是什么?ps,没错。有关于进程状态的信息都来自于ps命令,那是否是ps的输出在误导我呢?
答案是肯定的,ps的输出确实在一定程度上误导了我,先来看看ps命令的输出,ps有关于进程状态的输出共有7中,分别是:
D uninterruptible sleep (usually IO) //不可中断睡眠
R running or runnable (on run queue) //正在执行或可执行
S interruptible sleep (waiting for an event to complete) //可中断睡眠状态
T stopped, either by a job control signal or because it is being traced //停止或追踪状态
W paging (not valid since the 2.6.xx kernel) //换页,但2.6之后内核已不再可用
X dead (should never be seen) //死亡,但应该永远也看不到
Z defunct ("zombie") process, terminated but not reaped by its parent //僵死状态(已经终止但还没有被父进程回收)
以上内容来自于man ps中“PROCESS STATE CODES”一节。
好了,以上就是ps的输出了,那么源码中是如何定义的呢?让我们来看看源码中是如何定义的,相关定义位于./include/linux/sched.h中:
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4 进程的执行被暂停,当进程接收到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU信号后,进入暂停状态
#define __TASK_TRACED 8
/* in tsk->exit_state */
#define EXIT_DEAD 16
#define EXIT_ZOMBIE 32
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
/* in tsk->state again */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256
#define TASK_PARKED 512
#define TASK_STATE_MAX 1024
好了真相大白了,原来ps的输出与源码中的定义还不是完全一致的,这也就造成了我通过ps输出的结果与《Linux内核设计与实现》中写的内容不同。
既然是谈“僵死状态”,那就详细研究一下这个状态。“EXIT_ZOMBIE”状态表示进程的执行被终止(注意是已经终止了,而不是暂停,进程暂停了还能恢复),但是父进程还没有发布wait4()或waitpid()系统调用来返回有关死亡进程的信息。“EXIT_ZOMBIE”与“EXIT_DEAD”状态即可以存放在进程描述符的state字段中,也可以存放在exit_state字段中。
至此我们已经了解了ps的输出与内核源码的定义,让我们来看看他们之间的对应关系。
ps命令输出 | 内核源码定义 |
D uninterruptible sleep (usually IO) | TASK_UNINTERRUPTIBLE |
R running or runnable (on run queue) | TASK_RUNNING |
S interruptible sleep (waiting for an event to complete) | TASK_INTERRUPTIBLE |
T stopped, either by a job control signal or because it is being traced | __TASK_STOPPED or __TASK_TRACED |
W paging (not valid since the 2.6.xx kernel) | |
X dead (should never be seen) | 可能是EXIT_DEAD或TASK_DEAD,这一点还无法确认 |
Z defunct ("zombie") process, terminated but not reaped by its parent | EXIT_ZOMBIE or EXIT_TRACE |
最后让我们看看各进程状态之间转化关系图。这幅图是我在网上的图的基础上稍加改变得到的。