使用top查看系统资源使用情况,查看到cpu使用率较高,其中iowait很高,说明有进程在iowait上消耗很多资源,但是,通过top又没有办法定位是哪个进程搞得鬼,因此需要借助其他工具 iotop及通过一
些定位流程来确定是谁用了我的cpu。

iowait

“iowait” 是指系统中等待 I/O(Input/Output)操作完成的时间,通常以百分比表示。在Linux和类Unix系统中,iowait 是 top 和其他系统性能监控工具中的一个关键性能指标之一。

I/O 操作包括磁盘读写、网络传输等。当进程发出一个 I/O 请求(例如,从磁盘读取文件或从网络接收数据)后,它通常需要等待底层硬件设备或网络传输完成。这个等待过程就被称为 iowait。

高 iowait 百分比通常表示以下情况之一:

  • 磁盘繁忙:磁盘可能正在执行大量读写操作,因此新的 I/O 请求必须等待。
  • 磁盘故障:磁盘上的某些问题可能导致 I/O 操作的延迟或失败,从而增加了 iowait。
  • 网络延迟:在涉及网络 I/O 的情况下,iowait 可能会增加,因为网络通信可能需要更长时间。
  • 过多的 I/O 请求:系统上运行的进程过多,发出了大量的 I/O 请求,导致 I/O 队列堆积,从而增加了 iowait 时间。

iotop

iotop :查看各个进程iowait使用率的工具(我所使用的iotop使用c编写,单bin文件,编译方便,便于移植)
源码连接:iotop Ubuntu 18.04 x86:iotop x86版本 Ubuntu 18.04 arm:iotop arm版本

使用iotop排查IO占用高的流程:

  1. 定位线程ID: iotop查看占用高的TID
  2. 定位PID: 通过TID查PID,ps -eLf | grep <TID> 一般在COMMAD可以看到命令行信息
  3. 定位程序细节: 通过lsof -p <PID>查看进程打开的文件

排查流程

创建一个高io的进程

$ dd if=/dev/zero of=zero.txt bs=1M count=16000

查看系统资源占用top -d 1, 看可以看到 io有38.2%(io前的数字)的占用率。

Mem: 7748992K used, 140140K free, 654804K shrd, 108K buff, 6572532K cached
CPU:  0.5% usr  1.2% sys  0.5% nic 59.5% idle 38.2% io  0.0% irq  0.0% sirq
Load average: 1.80 0.65 0.33 1/211 32109
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
31975 31938 root     D     9868  0.1   1  1.3 /bin/dd if /dev/zero of zero.txt bs 1M count 16000
31974 28743 root     S    23352  0.3   3  0.2 ./iotop
31956 28720 root     R     8840  0.1   2  0.1 top -d 1
  526     2 root     SW       0  0.0   0  0.1 [kworker/0:1]
  557     2 root     SW       0  0.0   0  0.1 [kswapd0]
24953     2 root     DW       0  0.0   1  0.1 [kworker/u8:1]

定位线程ID

运行iotop, 可以看到ddkworker/u8:1占用率最高,分别对应TID为:2495331975 ,其中kworker为操作系统调用的进程。由于iotop展示的是TID,为线程ID,需要查看对应的进程ID。

$ sudo iotop
-----------------------------------------------------------------------------------------------------------------------------
  Total DISK READ:    0.00 B/s                                      |   Total DISK WRITE:    102.26 M/s                                     
Current DISK READ:    0.00 B/s                                      | Current DISK WRITE:    93.85 M/s                                    
TID     PRIO USER      DISK READ   DISK WRITE  SWAPIN    IO       GRAPH[IO]>                           COMMAND                                                                                                      
24953   be/4 root         0.00 B/s    0.00 B/s   0.00 %  100.00 %  ||||||||||||||                      kworker/u8:1      
31975   be/4 root       102.26 M/s    0.00 B/s   0.00 %   84.76 %  ||||||||||||||                      dd    
	''''                                                                                            
    5   be/0 root         0.00 B/s    0.00 B/s   0.00 %   0.00 %                                       kworker/0:0H

定位PID

查看TID对应的PID,可以看到已经定位是/bin/dd if /dev/zero of zero.txt bs 1M count 16000命令行导致的io占用率过高。

$ ps -eLf | grep 31975
root     31975 31938 31975 26    1 18:49 pts/10   00:00:08 /bin/dd if /dev/zero of zero.txt bs 1M count 16000

定位程序细节

但对于复杂进程,如别人写的代码(如开源代码)可能需要确定哪部分代码出现的问题,以便修复bug,需要查找更多线索,可以通过lsof -p <PID>查看是进程都打开了哪些文件,当然这里指的文件是广义的linux中文件(万物皆文件)。可以看到FD的状态,是读(r)还是写(w)。

$ lsof -p 31975
COMMAND   PID USER   FD   TYPE DEVICE   SIZE/OFF   NODE NAME
dd      31975 root  rtd    DIR   0,16        480    464 /
dd      31975 root  txt    REG   0,16    2963120    547 /bin/busybox
dd      31975 root  mem    REG   0,16    5776816  28934 /usr/lib/locale/locale-archive
dd      31975 root    0r   CHR    1,5        0t0   6213 /dev/zero
dd      31975 root    1w   REG   8,16 6023487488 551481 /tmp/zero.txt
dd      31975 root    2u   CHR 136,10        0t0     13 /dev/pts/10

当然存在一些 文件只有 NODE 没有 NAME ,可以通过stat查看状态。