iowait 的含义

iowait 是 CPU 的一种状态,表示此时 CPU 正处于 idle 状态,并且至少有一个进程正在等待 IO。

CPU 一共有四种状态。在任一时刻,CPU 的状态都是四种中的一种。这四种状态是:user, sys, idle iowait. 一般的程序,比如 sar top,会用百分比表示 CPU 分别处于这四种状态的时间,这四种状态相加的结果是 100%。

其实准确来说,CPU 只有两种状态:busy 和 idle。Busy 又分成了两种,user 和 system,可以表示 CPU 目前正在执行用户空间的代码,还是正在执行 kernel 空间的代码,方便开发者定位问题。Idle 又分成了两种:idle 和 iowait。笼统来说,idle 就是目前系统中没有 Runnable 的进程了(参考之前的博文:Linux 进程的生命周期),iowait 就是目前系统中没有 Runnable 进程(所以说 iowait 是 idle 的一种),并且,有进程卡在 IO 上。

(注意,本文说的“进程”是从资源调度的角度讲的,本文的语境中,进程包括线程)

统计的方式

Kernel 会定期更新 counter(AIX,CPU state counter 每个 clock interrrupt 更新,每 10ms 一个 interrupt)。

对于每次更新,检查 CPU 是否是 busy,如果是 busy,检查 CPU 在执行用户态还是内核态的代码,增加相应的计数器。如果不是 busy,那就是 idle,检查此 CPU 之前有没有发出 IO 操作,如果有,那么就增加 iowait,如果没有,那么就增加 idle 的计数器。(所以可以认为这个数值是抽样统计的方法?)

像 sar,top 这种展示工具,就去读 counter,计算时间段内的比例,展示结果。

举例说明含义

综上,假设 CPU state 出现了比较高的 iowait,那么就意味着:这个 CPU (在大部分时间)找不到可以执行的进程了,至少有一个进程在等待 IO。

iowait 只包括文件系统的 IO,不包括:sockets, pipes, ttys, select(), poll(), sleep(), pause()。

举例1: 一个机器有 4 个 CPU,1个CPU iowait 比较高,3 个 CPU user+sys 很高,iowait 很低。

意思是当前有 3 个 Runnable 的进程,有至少1个进程阻塞在 IO,其他的进程要么阻塞在 IO,要么阻塞在其他状态,但是不是 Runnable 状态,Runnable 状态的进程有且只有 3 个。因为如果再多来一个 Runnable,那么它就会被 iowait 高的那个 CPU 去执行,此 CPU 的 iowait 也不会很高了,user+sys 会变高。

举例2: 这个例子是参考资料 What exactly is “iowait”? 中的,非常典型。

假设有 6 个 CPU,而且只有 6 个进程:

  • 2个进程不涉及磁盘 IO 操作,只有 CPU 计算;
  • 4个进程要花 70% 的时间做 IO 操作,30% 的时间在 CPU 上计算,这 30% 中,5% 是在 kernel mode,25% 是在 user mode。

那么 CPU 利用率将会如下,最后一行是综合所有的 CPU 的数据:

现在,还是6个进程完全不变,但是 CPU 从6个减少到了4个,数据将会是如下:

可以看到,2个 100% 利用率的 CPU 保持不变,但是总的 CPU 的利用率是 80% 了。解释如下。

4个进程,每一个进程只要花 30% 的时间来计算,其他的时间是 iowait,iowait 是 idle 中的一种,iowait 的时候,如果能有别的事情可以做,CPU 就会去做别的事情。所以 2 个 CPU 每一个会花 60% 的时间做计算工作(一个进程是 25% + 5%,做完之后做下一个进程的 25% + 5%)。做完 60% 就无事可做了,剩下 40% 的 iowait(就是 idle)。

总结

iowait 是一种 idle,如果比例过高,它可以告诉我们几件事情:

  • 系统正在做的工作,大部分时间都是在等待 io 了,io 系统的性能不够高(也有可能是硬盘坏了);
  • CPU 没有更多的工作可以做了,我们可以给系统分配更多的计算工作;
  • 它不是 CPU 的一种“阻塞”状态,它不能说明:CPU 现在在等待 IO,无法运行其他进程。而是:没有可以运行的进程能给 CPU 做;

iowiat 是 CPU 角度的一个状态,它不是进程角度的状态。iowait 很低,不能代表进程没有卡在 IO 上。假设有一个进程需要花 70% 的时间做 io操作,把它放到一个空闲的,单 CPU 的系统中,显示的 iowait 是 70%,但是我在这个系统中增加一个不依赖 io 的计算任务,iowait 就变成 0 了。但是我们之前的那个进程,依然需要花 70% 的时间等待 io。所以,它不代表进程的状态。

参考内容:

  1. What exactly is “iowait”?


iowait 的含义”已经有11条评论

  1. >举例1: 一个机器有 4 个 CPU,1个CPU iowait 比较高,3个 CPU iowait 很低。

    >意思是当前有 3 个 Runnable 的进程
    “3 个 Runnable 的进程” 是怎么推断出来的呢?

    • 这里写的不好,原文修改了:是想说其他 3 个 CPU 都是 busy,推断出正好有 3 个 Runnable 的进程。

      感谢指出,现在好理解了吗

  2. 感谢!
    写的非常棒,今天过得是有意义的。
    iostat里是不是也有很多类似的 mystery ?

    应该如何衡量 – 卡在 IO 上?

    • 理解了它的含义,应该不会有 mystery 吧。

      卡在 io 上有两种情况:

      一种是应用是读写 io 太多了,cpu 大部分时间都是 iowait 状态,在等 io 完成。比如数据库这种存储类型的软件。

      另一种是硬盘坏了,io 需要更长的时间完成。这时候基本可以看到所有的 cpu 都有比较高的 iowait。

      • 补充一种iowait高的情况,在cpu降频的时候你会发现负载很低,磁盘读写也低,但是cpu io wait高

        • 没想明白这个道理。如果运行的程序不变,那么 CPU 降频的话,相同的工作应该造成更大的负载,所以负载应该变高,磁盘读写应该不受 CPU 的影响吧,等待磁盘的时间应该是一样的。

          难道是 CPU 频率降低,所以分给磁盘的工作的速度降低了吗?

  3. 您好,如果单核 CPU 上有一个 D 状态的进程,是不是意味着 iowait 100% 且无法运行其他进程了呢?

    • 你好,我是这么想的:如果系统完全只有一个进程,并且是 sleep 状态(D 对于 CPU 来说就是一种 idle 而已,只不过对于进程来说,直到它想要的操作完成,是不可以被打断的,即使 kill 也不可以),那么 iowait 确实是 100%。

      但是 iowait 是一种 sleep,所以这时候如果有另一个进程,会用 100% CPU,那么 CPU 就会变成 100% busy,0% iowait;如果有另一个进程,会使用 70% 的 CPU,那么 CPU 的状态就是 70% busy,30% iowait。CPU 是一种类似时间的资源,70% 的意思是 70% 的时间。iowait 100% 意味着 CPU 100% 的时间都是 iowait,即 idle。如果有其他进程想使用 CPU 是可以使用的。

      • 醍醐灌顶!一个是从进程角度来看一个是从 CPU 角度来看的。一个 D 状态的进程意味着它不会被打断,但并不能说明 CPU 把时间片分配到其他进程上面。所以如果有其他进程想使用 CPU 是可以使用的。

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注