Contents

Linux过程状态

1. 概述

在本文中,我们将了解 Linux 中的进程状态。特别是,我们将了解 Linux 进程在生命周期各个部分的五种不同状态中的每一种。此外,我们还将研究可用于读取系统中每个进程状态的不同工具。

2. Linux进程状态

在 Linux 中,进程是执行程序或命令的实例。虽然存在这些进程,但它们将处于五种可能状态之一:

  • 正在运行或可运行 (R)
  • 不间断睡眠 (D)
  • 可中断睡眠 (S)
  • 停止 (T)
  • 僵尸 (Z)

为了可视化流程的生命周期,我们可以在有限状态机中对其建模:

/uploads/process_states/1.jpeg

对于任何 Linux 进程,它们的起点是它们被创建的那一刻。例如,父进程可以使用fork() 系统调用来启动子进程。**一旦启动,进程就会进入运行或可运行状态。**当进程正在运行时,它可能会进入一个代码路径,要求它在继续之前等待特定的资源或信号。在等待资源时,进程会通过进入两种休眠状态之一来自愿放弃 CPU 周期。

此外,我们可以暂停正在运行的进程并将其置于停止状态。通常,这是通过向进程发送SIGSTOP信号来完成的。 处于此状态的进程将继续存在,直到它被终止或使用SIGCONT恢复。最后,进程在终止并进入僵尸状态时完成其生命周期,直到其父进程将其从进程表中清除。

2.1. 运行或可运行状态 (R)

当一个新进程启动时,它将被置于运行或可运行状态。**在运行状态下,进程占用一个CPU核来执行它的代码和逻辑。**但是,线程调度算法可能会强制正在运行的进程放弃其执行权。这是为了确保每个进程都能公平地共享 CPU 资源。在这种情况下,进程将被放入一个运行队列中,并且它的状态现在是可运行状态,等待轮到它执行。

尽管正在运行和可运行状态是不同的,但它们被共同分组为一个由字符R表示的状态。

2.2. 睡眠状态:可中断(S)和不可中断(D)

在流程执行期间,它可能会遇到需要请求外部资源的部分代码。主要是,对这些资源的请求是基于 IO 的,例如从磁盘读取文件或进行网络请求。由于没有资源,进程无法继续,它会停止并且什么也不做。在此类事件中,它们应该将 CPU 周期放弃给其他准备运行的任务,因此它们会进入休眠状态。

有两种不同的休眠状态:不可中断休眠状态(D)和可中断休眠状态(S)。不可中断的休眠状态只会等待资源可用后才会转入可运行状态,它不会对任何信号作出反应。另一方面,可中断睡眠状态将对信号和资源可用性做出反应。

2.3. 停止状态 (T)

从运行或可运行状态,我们可以使用SIGSTOP或 SIGTSTP信号将进程置于停止状态 (T) 。这两个信号之间的区别在于我们发送SIGSTOP是程序化的,例如运行kill -STOP {pid}。此外,该进程不能忽略此信号并将进入停止状态。另一方面,我们使用键盘*CTRL + Z发送SIGTSTP*信号。与SIGSTOP不同,进程可以选择忽略此信号并在收到SIGTSTP后继续执行。

在这种状态下,我们可以通过发送SIGCONT信号使进程恢复到运行或可运行状态。

2.4. 僵尸状态 (Z)

**当一个进程完成执行或终止时,它会向父进程发送SIGCHLD信号并进入僵尸状态。**僵尸进程,也称为失效进程,将保持此状态,直到父进程将其从进程表中清除。要从进程表中清除已终止的子进程,父进程必须使用wait() 或 waitpid() 系统调用读取子进程的退出值。

3. 检查进程状态

在 Linux 中有多种方法可以检查进程的状态。例如,我们可以使用ps和 top等命令行工具来检查进程的状态。或者,我们可以查阅特定 PID 的伪状态文件。

3.1. 使用 ps显示进程状态

要使用 ps 显示进程状态,让我们运行ps命令以包含一个告诉我们进程状态的列:

$ ps a
    PID TTY      STAT   TIME COMMAND
   2234 tty2     Ssl+   0:00 /usr/lib/gdm3/gdm-x-session --run-script env GNOME_SHELL_SESSION_MODE=ubuntu /usr/bin/gnome-session --systemd --session=ubuntu
   2237 tty2     Rl+    0:07 /usr/lib/xorg/Xorg vt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3
   2287 tty2     Sl+    0:00 /usr/libexec/gnome-session-binary --systemd --systemd --session=ubuntu
   2982 pts/0    Ss     0:00 bash
   3467 pts/0    R+     0:00 ps a

** STAT列下的值的第一个字母表示进程所处的状态,**例如PID为2234的进程当前处于可中断休眠状态,用字符S表示。除此之外,我们还可以观察到进程 2237 当前处于运行或可运行状态。

此外,我们可以看到除了每个状态字符之外还有其他字符。这些字符表示进程状态的几个属性。例如,小写字母s表示进程是会话领导者。有关每个字符含义的完整列表,我们可以在官方手册页 上找到它。

3.2. 使用top命令

在 Linux 中,top 命令行工具以实时方式显示进程详细信息。它显示了系统的不同方面,例如各个进程的内存和 CPU 使用情况。要查看进程状态,让我们在终端中运行top

Tasks: 183 total,   1 running, 182 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  1.1 sy,  0.0 ni, 97.1 id,  0.4 wa,  0.0 hi,  0.7 si,  0.0 st
MiB Mem :   3936.4 total,   1925.0 free,    850.6 used,   1160.8 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   2834.2 avail Mem 
    PID USER  PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   2237 bob   20   0  252252  81740  49204 S   2.3   2.0   0:09.37 Xorg
   2519 bob   20   0 3428664 375256 125080 S   2.0   9.3   0:19.57 gnome-shell
   2909 bob   20   0  966852  49944  37308 S   1.0   1.2   0:02.28 gnome-terminal-
      1 root  20   0  103500  13312   8620 S   0.7   0.3   0:04.44 systemd
   3588 bob   20   0   20600   3936   3380 R   0.3   0.1   0:00.01 top
      2 root  20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd
      3 root   0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp

**在top命令输出的底部,我们可以找到S列,它显示了每个进程的状态。**与ps命令相反,  top命令显示每个进程的状态,而没有额外的进程属性。

3.3. /proc伪文件

/proc伪文件系统包含有关我们系统中进程的所有信息。因此,我们可以通过这个伪文件系统直接读取进程的状态。这种方法的缺点是我们首先需要知道进程的 PID,然后才能读取它的状态。

*要获取进程的状态,我们可以从/proc/{pid}/status下的 伪status文件中提取值。*例如,我们可以通过读取文件/proc/2519/status来获取 PID 为 2519 的进程的状态 :

$ cat /proc/2519/status | grep State
State:	S (sleeping)