查看磁盘文件读写信息

       我们在问题调查中有时候会看到磁盘很忙但是就是不知道谁在写,本文介绍几个简单方法能够比较方便的看到磁盘写的细节。

       首先,来看看IO协议栈的大致样子,然后我们就知道所谓的查看磁盘读写的工具到底如何工作的了。

       点击[这里]看协议栈图示,从图上可以看到,如果我们要做IO探查工具,首选位置肯定是Block I/O layer这一层,因为所有的IO都流经这里,只要我们能在这里挂个钩子,就可以拦截IO请求。好在这事有人干了,我们不必费功夫,拿来用用就可以了。

       第一种方法:

       sudo bash -c 'echo 1 > /proc/sys/vm/block_dump’

    block_dump enables block I/O debugging when set to a nonzero value.

       设置之后,block层处理的IO请求都会将摘要信息print到缓冲区中,可以通过dmesg查看。比如

$dmesg |grep READ|tail -n 5
[5398830.201151] sqlonline_worke(44545): READ block 95399288 on sda6
[5398830.201175] sqlonline_worke(44168): READ block 95250360 on sda6
[5398830.201197] sqlonline_worke(44095): READ block 95250352 on sda6
[5398830.201200] sqlonline_worke(44545): READ block 95399312 on sda6
[5398830.201567] sqlonline_worke(44545): READ block 95399368 on sda6

     每行一个操作,分别表示哪个进程在何时在哪个磁盘(分区)上读写了哪个block,需要注意的是,这里面的block是不是我们说的文件系统的block,是硬件层面的block,可以看做是扇区。每个扇区大小512B,绝大部分的文件系统block都是4K,所以从扇区推算文件系统block只要除以8就可以了,比如95399312的文件系统block是11924914。

  接下来可以使用debugfs

[2]

来查看该文件的inode以及文件名。
  Debugfs exists as a simple way for kernel developers to make information available to user space. 
  这里用到的debugfs很简单,其余命令可以man。
$sudo mount -t debugfs none /sys/kernel/debug
$sudo debugfs -R 'open /dev/sda6'

$sudo debugfs -R 'icheck 11924914' /dev/sda6
debugfs 1.41.12 (17-May-2010)
Block   Inode number
11924914        524309

$sudo debugfs -R 'ncheck 524309' /dev/sda6
debugfs 1.41.12 (17-May-2010)
Inode   Pathname
524309  /xx/yy/zz.log

 

第二种办法:
    使用blktrace

[3]

工具,这个工具包含了通用块层和调度层的信息,可以更精确的得到一个IO请求各个阶段的信息,这个本身有不少值得写的,我们只看最简单的用法。
    blktrace is a block layer IO tracing mechanism which provides detailed information about request queue operations up to user space.

         Blktrace是标准工具,一般系统都是安装好了的,如果没有安装,可以yum install一下。

     

sudo blktrace -d /dev/sda -o b.log
停一会就可以ctrl-c
blkparse b.log.blktrace.* > b.log.parsed
解析输出文件

一个IO请求可以分为很多阶段,包括设备映射,构造请求,插入队列,调度,执行,完成;这些blktrace都能跟踪,并能给出每个阶段的时间,这里不管这么多我们只是看哪些文件被读写。搜索A(mapping)然后

8,0    6        2     0.000066079 112506  A   R 468922741 + 256 <- (8,6) 169117648
(8,6)表示sda第六个分区,即sda6
169117648/8= 21139706
$sudo debugfs -R 'icheck 21139706' /dev/sda6
debugfs 1.41.12 (17-May-2010)
Block   Inode number
21139706        1442128

$sudo debugfs -R 'ncheck 1442128' /dev/sda6
debugfs 1.41.12 (17-May-2010)
Inode   Pathname
1442128 /xx/worker.LOG
第三种办法:
    使用systemtap,这个是通用工具,追踪IO只是功能之一,有点杀鸡用牛刀的感觉,不详细介绍。麻烦的地方在于环境准备,之前有过一篇安装说明[4],如果安装完成,则可以直接使用一个公开的脚本检查IO,见disktop脚本[5]。该脚本的问题是只检查vfs.read/write接口,该接口工作在通用块层以上,所以部分IO请求,比如缺页swapper加载数据的IO是追踪不到的(我们这次碰到的问题就是swapper导致的),这时候就需要追踪ioblock.end这些更底层的接口信息。
 通过以上方法就能知道是哪些进程在频繁的读写哪些文件,可以帮助定位问题。不过IO是个很复杂的体系,我也只了解皮毛,就将调查问题过程中的信息记录下来方便以后使用。

[1].     Linux IO stack http://www.thomas-krenn.com/de/wikiDE/images/2/22/Linux-io-stack-diagram_v0.1.pdf

[2].     Debugfs : https://www.kernel.org/doc/Documentation/filesystems/debugfs.txt

[3].     Blktrace : http://pdfedit.petricek.net/bt/file_download.php?file_id=17&type=bug

[4].     Systemtap 安装手册:http://www.cnblogs.com/raymondshiquan/archive/2012/08/16/2643011.html

[5].     Disktop stp脚本:https://sourceware.org/systemtap/examples/io/disktop.stp

 

posted on 2014-08-12 14:20  RaymondSQ  阅读(1790)  评论(0编辑  收藏  举报