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