✏️ update
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
## 什么是不可中断状态
|
||||
|
||||
当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,可以发现它们都处于 D 状态,也就是不可中断状态 (Uninterruptible Sleep)。
|
||||
当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,可以发现它们都处于 D 状态,也就是不可中断状态 (Uninterruptible Sleep)。
|
||||
|
||||
不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有 I/O 性能问题。
|
||||
|
||||
@ -10,8 +10,7 @@
|
||||
|
||||
特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
|
||||
|
||||
举个最常见的网卡接收数据包的例子:网卡接收到数据包后,会通过 __硬件中断__ 的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个 __软中断__ 信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据
|
||||
进行逐层解析和处理,直到把它送给应用程序。
|
||||
举个最常见的网卡接收数据包的例子:网卡接收到数据包后,会通过 __硬件中断__ 的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个 __软中断__ 信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
|
||||
|
||||
Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
|
||||
|
||||
@ -24,7 +23,7 @@ Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类
|
||||
|
||||
## 什么是僵死(僵尸)进程
|
||||
|
||||
僵死(僵尸)进程进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死(僵尸)。
|
||||
僵死(僵尸)进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死(僵尸)。
|
||||
|
||||
通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。
|
||||
|
||||
@ -32,7 +31,7 @@ Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类
|
||||
|
||||
#### top 命令查看进程状态
|
||||
|
||||
top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。
|
||||
top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。
|
||||
|
||||
```
|
||||
top - 21:43:31 up 28 days, 23:44, 2 users, load average: 0.02, 0.02, 0.00
|
||||
@ -50,19 +49,19 @@ KiB Swap: 0 total, 0 free, 0 used. 3169024 avail Mem
|
||||
3 root 20 0 0 0 0 S 0.0 0.0 0:33.16 ksoftirqd/0
|
||||
```
|
||||
|
||||
- __R__ 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正 在等待运行。
|
||||
- __R__ 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
|
||||
|
||||
- __D__ 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般 表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
|
||||
- __D__ 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
|
||||
|
||||
- __Z__ 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它 表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
|
||||
- __Z__ 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它 表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
|
||||
|
||||
- __S__ 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件 而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
|
||||
|
||||
- __I__ 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件 交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升 高, I 状态的进程却不会。
|
||||
- __I__ 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
|
||||
|
||||
- __T__ 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你 用 fg 命令,恢复到前台运行)。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪 状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
|
||||
- __T__ 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你 用 fg 命令,恢复到前台运行)。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
|
||||
|
||||
- __X__ 是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令 中看到它。
|
||||
- __X__ 是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。
|
||||
|
||||
#### ps 命令查看进程状态
|
||||
|
||||
@ -79,4 +78,4 @@ root 12913 0.0 0.0 12944 928 pts/1 S+ 21:55 0:00 grep --color=au
|
||||
|
||||
进程组和会话。它们用来管理一组相互关联的进程,进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;而会话是指共享同一个控制终端的一个或多个进程组。
|
||||
|
||||
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
|
||||
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
|
Reference in New Issue
Block a user