Linux过程状态
1. 概述
在本文中,我们将了解 Linux 中的进程状态。特别是,我们将了解 Linux 进程在生命周期各个部分的五种不同状态中的每一种。此外,我们还将研究可用于读取系统中每个进程状态的不同工具。
2. Linux进程状态
在 Linux 中,进程是执行程序或命令的实例。虽然存在这些进程,但它们将处于五种可能状态之一:
- 正在运行或可运行 (R)
- 不间断睡眠 (D)
- 可中断睡眠 (S)
- 停止 (T)
- 僵尸 (Z)
为了可视化流程的生命周期,我们可以在有限状态机中对其建模:
对于任何 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)