Linux - 进程 - 进程状态

159 阅读5分钟

一. 查看进程状态

ps

查看进程, 最常使用的命令是 ps(process status). ps 有许多选项, 它最简单的使用形式是这样的:

image.png

上例中, 列出了两个进程, 进程 4892 和进程 7719, 各自代表命令 bashps. 正如我们所看到的, 默认情况下, ps 不会显示很多进程信息, 只是列出与当前终端会话相关的进程. 为了得到更多信息, 我们需要加上一些选项, 但是在这样做之前, 我们先看一下 ps 命令运行结果的其它字段. TTY 是 "Teletype"(直译电传打字机) 的简写, 指的是进程的控制终端. TIME 字段表示进程运行过程中占用 CPU 的总时间. CMD 表示启动进程的命令名称. 正如我们所看到的, 计算机使这两个进程工作起来不需要消耗很多资源.

ps aux

image.png

  • USER: 进程所有者的用户名.

  • PID: 进程的唯一标识符, 即进程 ID.

  • %CPU: 进程使用的 CPU 资源的百分比.

  • %MEM: 进程使用的 内存 资源的百分比.

  • VSZ: (Virtual Memory Size) 进程的虚拟内存大小. (以 KB 为单位)

  • RSS: (Resident Set Size) 进程占用的物理内存大小. (以 KB 为单位)

  • TTY: 进程所关联的终端.

  • STAT: 进程的状态. (例如, R 表示运行状态, S 表示睡眠状态, Z 表示僵死状态等)

  • START: 进程启动的时间.

  • TIME: 进程运行过程中占用 CPU 的总时间.

  • COMMAND: 启动进程的命令名称.

top

虽然 ps 命令能够展示许多计算机运行状态的信息,但是它只是提供 ps 命令执行时刻的机器状态快照. 为了看到更多动态的信息, 我们使用 top 命令.

top 程序以进程活动顺序显示连续更新的系统进程列表, 默认情况下, 每三秒钟更新一次. 同时, top 显示结果由两部分组成: 最上面是系统概要, 下面是进程列表, 以 CPU 的使用率排序.

image.png

这个命令对所有正在运行的进程和系统负荷提供不断更新的概览信息, 包括系统负载, CPU 利用分布情况, 内存使用, 每个进程的内容使用情况等信息.

top展示界面从上到下由4部分组成

  1. 概览区域
  2. 输入/消息行, 位于概览区域和表头之间
  3. 表头
  4. 任务区域

概览区域中每个字段的意义如下图所示:

image.png

二. 进程状态

volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */

进程描述符 task_struct 中的 state 字段描述了进程当前所处的状态. 它由一组标志位组成, 其中每一个标志位描述一种可能的进程状态. 在当前的 Linux 版本中, 这些状态是互斥的, 因此, 严格意义上说, 只能设置一种状态, 其余的标志位将被清除, 下面是进程可能的状态.

#define TASK_RUNNING            0
#define TASK_INTERRUPTIBLE      1
#define TASK_UNINTERRUPTIBLE    2
#define TASK_STOPPED            4
#define TASK_TRACED             8
#define EXIT_ZOMBIE             16
#define EXIT_DEAD               32

可运行状态 (TASK_RUNNING)

进程要么在 CPU 上执行, 要么准备执行.

可中断的等待状态 (TASK_INTERRUPTIBLE)

进程被挂起 (睡眠), 直到某个条件变为真. 产生一个硬件中断, 释放进程正等待的系统资源, 或传递一个信号都是可以唤醒进程的条件. (把进程的状态调回 TASK_RUNNING)

不可中断的等待状态 (TASK_UNINTERRUPTIBLE)

与可中断的等待状态类似, 但有一个例外, 把信号传递到处于该状态下的进程不能改变该进程的状态. 这种状态很少用到, 但在一些特定的情况下 (进程必须等待, 直到一个不能被中断的事件完成), 这种状态是很有用的. 例如, 当进程打开一个设备文件, 其相应的设备驱动程序开始探测相应的硬件设备时会用到这种状态. 探测完成以前, 设备驱动程序不能被中断, 否则, 硬件设备会处于不可预知的状态.

暂停状态 (TASK_STOPPED)

进程的执行被暂停, 当进程接收到 SIGSTOP, SIGTSTP, SIGTTINSIGTTOU 信号后, 进入暂停状态.

image.png

跟踪状态 (TASK_TRACED)

进程的执行已由 debugger 程序暂停, 当一个进程被另一个进程监控时 (例如 debugger 执行 ptrace()系统调用监控一个测试程序), 任何信号都可以把这个进程置于 TASK_TRACED 状态.

long exit_state;

还有两个进程状态是既可以存放在进程描述符的 state 字段中, 也可以存放在 exit_state 字段中. 从这两个字段的名称可以看出, 只有当进程的执行被终止时, 进程的状态才会变为这两种状态中的一种:

僵死状态 (EXIT_ZOMBIE)

进程的执行被终止, 但是, 父进程还没有使用 wait()waitpid() 系统调用来返回有关已被终止进程的信息. 发布 wait() 类系统调用前, 内核不能丢弃存放在已被终止进程的进程描述符中的数据, 因为父进程可能还需要它来判断自己分配给子进程的任务的完成情况.

僵死撤销状态 (EXIT_DEAD)

最终状态, 由于父进程刚发出 wait()waitpid() 系统调用, 因而子进程被系统移除. 为了防止其他执行线程在同一个进程上也执行 wait() 类系统调用, 而把进程的状态由 EXIT_ZOMBIE 状态改为 EXIT_DEAD 状态.

Linux 内核中对于进程状态同时有如下定义, 与 state 字段中的七种状态是一一对应的.

/*
 * The task state array is a strange "bitmap" of
 * reasons to sleep. Thus "running" is zero, and
 * you can test for combinations of others with
 * simple bit tests.
 */
 static const char *task_state_array[] = {
	"R (running)",		/*  0 */
	"S (sleeping)",		/*  1 */
	"D (disk sleep)",	/*  2 */
	"T (stopped)",		/*  4 */
	"T (tracing stop)",	/*  8 */
	"Z (zombie)",		/* 16 */
	"X (dead)"		/* 32 */
};