处于“可中断睡眠”状态的进程怎么会使用 100% 的 CPU?

处于“可中断睡眠”状态的进程怎么会使用 100% 的 CPU?

根据这个参考,一个进程有以下状态

R  running or runnable (on run queue)
D  uninterruptible sleep (usually IO)
S  interruptible sleep (waiting for an event to complete)
Z  defunct/zombie, terminated but not reaped by its parent
T  stopped, either by a job control signal or because it is being traced

在睡眠状态下,进程不会消耗 CPU 时间,但是在下面的输出中,我看到一个进程使用了​​ 100% 的 CPU,同时它处于 S 状态。

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
32643 root      20   0 13736 7748  472 R   98  0.0   2:59.30 bzip2
29504 satam     20   0 1063m 779m 3824 S  100  2.4   1242:54 stencil
31923 root      20   0 15092 1224  848 D   14  0.0   1:39.96 find

这怎么可能?这意味着什么?

答案1

“不可中断睡眠”意味着进程正在等待 I/O(例如磁盘操作)。但是,如果 CPU 正在运行该进程,即使它没有工作,CPU 仍然“卡住”等待它完成 io,以便它可以继续执行其他任务 - 安排另一项任务。因此,当进程处于 D 模式时,这会消耗 100% 的 CPU 周期。

因此它处于睡眠模式,此时它不执行任何 CPU 工作,但不可中断,这意味着 CPU 不能执行任何其他操作。

在多核系统中,其他核心可用于执行其他任务。

答案2

我们来看一看图片:

 PID  USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
29504 satam     20   0 1063m 779m 3824 S  100  2.4   1242:54 stencil

该进程处于“S”状态,但 CPU 使用率 = 100%。

虽然这没有任何意义,但是我们现在就会找到它。

“Top” 显示的是当前进程的状态。它是特定时间点的特征。因此,进程“当前”处于休眠状态。

但是 CPU 使用率不是时间实例的特征,而是时间间隔的特征。它是从现在到之前某个时间之间的时间间隔内的平均 CPU 使用率:从 (t-delta) 到 t。其中 t 是当前时刻。

因此,现在该进程处于休眠状态,其 CPU 使用率为 0%。但是(例如)1 秒前,该进程的 CPU 使用率为 100%。因此,top 进行计算:(100%+0%)/1s = 100%。

是否有意义?

因此,“S” 是当前进程的状态。但 CPU 使用率列是从现在到之前某个时间的平均 CPU 使用率。这就是它的意义所在。

让我再举一些例子:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                   
11568 vasya     20   0 28,558g 175004  92304 S   5,6  1,1  10:33.09 chrome

Chrome 处于“S”状态,但 top 显示它使用了 5.6% 的 CPU。这毫无意义。处于“S”状态的进程怎么会消耗 CPU?对吧?其实这很有道理。

该进程现在处于“S”状态。但是之前它处于“R”状态。

看,让我们快速检查一下 chrome 的状态:

$ while true; do cat /proc/11568/stat | awk '{print $3}'; done
S
S
R
S
S
S
S
S
S
S
S
R
S
S

大多数情况下,chrome 处于“S”状态,因此“top”很有可能会从 procfs 读取“S”状态并显示给我们。但这并不意味着 chrome 一直处于“S”状态,正如您所见。

因此,如果在时间点 = 0 秒时 CPU 使用率为 5.6%(状态“R”),而在下一时间点 =1 秒时 CPU 使用率为 0%(状态“S”),则进行计算以找出平均值 => (5.6%+0)/(1-0) = 5.6%

该进程现在处于休眠状态。(“S”列)。但是 CPU 使用率与当前特性无关。它是进程在过去三秒内 CPU 使用率的平均值。(默认情况下,top 每三秒刷新一次)。

希望它能够澄清这个话题。

相关内容