Linux 2.6内核版本后, 在proc文件系统中, 加入了存入磁盘IO访问数据的文件diskstats, 查看文件就可以获得某一时刻的累计访问值.

$ cat /proc/diskstats
  ……
  8    0 sda 130767120 478199 2848404253 865895766 …
  8    1 sda1 58 740 1598 96 2 0 4 0 0 96 96
  8    2 sda2 4031326 3249 64502142 3693948 5273723 …
  8    3 sda3 142 3261 4030 865 538334 302764 …
  8    4 sda4 1 0 2 3 0 0 0 0 0 3 3
  8    5 sda5 57717 8304 2083594 152577 2023051 …
  8    6 sda6 3283 617 126914 18536 1965077 …
  8    7 sda7 31 1062 1348 164 0 0 0 0 0 121 164
  8    8 sda8 63475 1067 1170446 364557 1050986 …
  8    9 sda9 409 1423 4454 2141 579616 2614979 …
  8  10 sda10 30 352 1668 130 0 0 0 0 0 125 130
  ……

    在实际的编程中, 有两个问题要处理, 一个是如何找出磁盘, 并将分区过滤掉, 因为Linux会同步更新磁盘分区及磁盘的数据, 如果不加区分, 数据就会不准确, 这个可以通第2列及第3列加以区分, 第二列为16的倍数的表示是磁盘而非分区, 第三列是磁盘名字, 一般的系统中磁盘都是小写的sd开头的. 对于普通的scsi磁盘, 只要找出第二列是16的倍数, 并且第三列前两个字母是”sd”的, 就表示是真正的磁盘, 比如前面的数据中, 只能取第一行. 为什么是16的倍数, 估计和一块盘最多有16个分区有关吧.

    磁盘中, 第四列后的都是性能数据, 各列的官方解释如下.

Field  1 ― # of reads completed
    This is the total number of reads completed successfully.
Field  2 ― # of reads merged, field 6 ― # of writes merged
    Reads and writes which are adjacent to each other may be merged for
    efficiency.  Thus two 4K reads may become one 8K read before it is
    ultimately handed to the disk, and so it will be counted (and queued)
    as only one I/O.  This field lets you know how often this was done.
Field  3 ― # of sectors read
    This is the total number of sectors read successfully.
Field  4 ― # of milliseconds spent reading
    This is the total number of milliseconds spent by all reads (as
    measured from __make_request() to end_that_request_last()).
Field  5 ― # of writes completed
    This is the total number of writes completed successfully.
Field  7 ― # of sectors written
    This is the total number of sectors written successfully.
Field  8 ― # of milliseconds spent writing
    This is the total number of milliseconds spent by all writes (as
    measured from __make_request() to end_that_request_last()).
Field  9 ― # of I/Os currently in progress
    The only field that should go to zero. Incremented as requests are
    given to appropriate struct request_queue and decremented as they finish.
Field 10 ― # of milliseconds spent doing I/Os
    This field is increases so long as field 9 is nonzero.
Field 11 ― weighted # of milliseconds spent doing I/Os
    This field is incremented at each I/O start, I/O completion, I/O
    merge, or read of these stats by the number of I/Os in progress
    (field 9) times the number of milliseconds spent doing I/O since the
    last update of this field.  This can provide an easy measure of both
    I/O completion time and the backlog that may be accumulating.

    另一个问题, 当Linux接到存贮时, 可能会有多条通路, 形成很多的虚盘, 这时不能取虚盘的性能数据, 比如连到EMC的存贮时, 第三列的名字应当为emcpower开头, 而不是sd开头了. 在Linuxmon程序中, 可以通过disk参数, 指定磁盘的前缀名字.

$ linuxmon.bin disk=emcpower
… Read RTim Writ WTim Busy Time
…  70    0  57    0    0  39
…  65    0  55    0    0  40
…  100    0  162    0    0  112
…  70    0  57    0    0  36
…  65    0  70    0    0  64
…  76    0  55    0    0  33
…  105    2  98    0    0  74
…  65    0  54    0    0  38
…  155    0  102    0    0  85
…  76    0  63    0    0  49
…  64    0  54    0    0  38
…  53    0  34    0    0  22

    如果上面的理解有问题, 欢迎指出来, 正在学习之中, 有理解错误也是难免的.