iostat等命令看到的是系统级的统计,比如下例中我们看到/dev/sdb很忙,如果要追查是哪个进程导致的I/O繁忙,应该怎么办?

1
2
3
4
5
6
7
8
9
# iostat -xd
.
util
0.00
85.03
0.00
0.00
0.00
.

进程的内核数据结构中包含了I/O数量的统计:

1
2
3
4
5
{
.
;
.
;

可以直接在 /proc/<pid>/io 中看到:

1
2
3
4
5
6
7
8
# cat /proc/3088/io
//在read(),pread(),readv(),sendfile等系统调用中读取的字节数
//在write(),pwrite(),writev(),sendfile等系统调用中写入的字节数
//调用read(),pread(),readv(),sendfile等系统调用的次数
//调用write(),pwrite(),writev(),sendfile等系统调用的次数
//进程读取的物理I/O字节数,包括mmap pagein,在submit_bio()中统计的
//进程写出的物理I/O字节数,包括mmap pageout,在submit_bio()中统计的
//如果进程截短了cache中的文件,事实上就减少了原本要发生的写I/O

我们关心的是实际发生的物理I/O,从上面的注释可知,应该关注 read_bytes 和 write_bytes。请注意这都是历史累计值,从进程开始执行之初就一直累加。如果要观察动态变化情况,可以使用 pidstat 命令,它就是利用了/proc/<pid>/io 中的原始数据计算单位时间内的增量:

1
2
3
4
5
6
7
8
# pidstat -d 2 2
)
 
Command
dd
 
Command
dd

另外还有一个常用的命令 iotop 也可以观察进程的动态I/O:

1
2
3
4
5
6
s
          
direct
24
]
.

pidstat 和 iotop 也有不足之处,它们无法具体到某个硬盘设备,如果系统中有很多硬盘设备,都在忙,而我们只想看某一个特定的硬盘的I/O来自哪些进程,这两个命令就帮不上忙了。怎么办呢?可以用上万能工具SystemTap。比如:我们希望找出访问/dev/sdb的进程,可以用下列脚本,它的原理是对submit_bio下探针:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#! /usr/bin/env stap
 
device_of_interest
 
{
1
)
}
 
)
{
bd_dev
)
,
)
}

这个脚本需要在命令行参数中指定需要监控的硬盘设备号,得到这个设备号的方法如下:

1
2
3
4
5
6
# ll /dev/sdb
sdb
 
0x8
0x00010
0x800010

执行脚本,我们看到:

1
2
3
4
5
6
7
8
# ./dev_task_io.stp 0x800010
0x800010
512
512
512
512
512
.

结果很令人满意,我们看到是进程号为31202的dd命令在对/dev/sdb进行读操作。

 

转载自:

linuxperf.com/?cat=11

相关文章:

  • 2021-10-30
  • 2021-12-10
  • 2022-02-05
  • 2021-06-25
  • 2021-05-17
  • 2022-12-23
  • 2021-05-20
猜你喜欢
  • 2022-12-23
  • 2021-07-27
  • 2021-10-02
  • 2021-06-03
  • 2022-12-23
  • 2021-12-17
  • 2021-06-24
相关资源
相似解决方案