如何在linux上编程从/ proc获取每秒磁盘读/写字节数?

时间:2016-05-16 07:40:42

标签: linux profiling disk

目的:我希望获得iostat命令可以获取的信息。

我已经知道,如果打开/proc/diskstats/sys/block/sdX/stat,则有以下信息:扇区读取扇区写入。所以如果我想得到读/写字节/ s,下面的公式是对的吗?

  

每秒读/写字节数
  (扇区读/写(现在) - 段读/写(最后))* 512字节/时间间隔

     

每秒读/写操作
  (读/写IOs(现在)+读/写合并(现在)-read / write IOs(last)-read / write merges(last))/ time interval

因此,如果我有一个计时器,每个第二个控制软件从这两个文件中读取信息,然后使用上面的公式来计算值。可以得到正确的答案吗?

1 个答案:

答案 0 :(得分:12)

TLDR扇区 512字节octets; 1扇区是512字节;每个字节是8位;每个位是0或1,但不是它们的叠加)。

"建立了磁盘512字节的标准扇区大小.... [dubious-discuss] " (c)维基https://en.wikipedia.org/wiki/Disk_sector

如何在linux中检查io统计信息的扇区大小(在/proc中):

检查iostat工具的工作原理(以iostat 1启动时显示每秒千字节数) - 它是sysstat包的一部分:

https://github.com/sysstat/sysstat/blob/master/iostat.c

 * Read stats from /proc/diskstats.
void read_diskstats_stat(int curr)
...
        /* major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */
        i = sscanf(line, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %u %u %u %u",
               &major, &minor, dev_name,
               &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec,
               &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks);

        if (i == 14) {
....
            sdev.rd_sectors = rd_sec_or_wr_ios;
....
            sdev.wr_sectors = wr_sec;
....

 * @fctr    Conversion factor.
...
        if (DISPLAY_KILOBYTES(flags)) {
            printf("    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn\n");
            *fctr = 2;
        }
...
    /*       rrq/s wrq/s   r/s   w/s  rsec  wsec  rqsz  qusz await r_await w_await svctm %util */
    ... 4 columns skipped
    cprintf_f(4, 8, 2,
          S_VALUE(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr,
          S_VALUE(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr,

因此,读取扇区计数并除以2得到千字节/秒(看起来像1扇区读取是0.5kb读取; 2扇区读取是1kb读取,依此类推)。我们可以得出结论,扇区总是512字节。文档中说明的相同,不是吗?:

互联网搜索" / proc / diskstats" - >

https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats - >

https://www.kernel.org/doc/Documentation/iostats.txt" I / O统计字段"来自美国的ricklind的ibm

Field  3 -- # of sectors read
    This is the total number of sectors read successfully.

Field  7 -- # of sectors written
    This is the total number of sectors written successfully.

此处没有关于行业规模的信息(为什么?)。源代码是最好的文档(它可能是)吗? /proc/diskstats的作者位于文件block/genhd.c的内核源代码中,函数diskstats_show

http://lxr.free-electrons.com/source/block/genhd.c?v=4.4#L1149

1170                 seq_printf(seqf, "%4d %7d %s %lu %lu %lu "
1171                            "%u %lu %lu %lu %u %u %u %u\n",
...
1176                            part_stat_read(hd, sectors[READ]),
...
1180                            part_stat_read(hd, sectors[WRITE]),

结构sectorshttp://lxr.free-electrons.com/source/include/linux/genhd.h?v=4.4#L82

中定义
 82 struct disk_stats {
 83         unsigned long sectors[2];       /* READs and WRITEs */

使用part_stat_read阅读并使用__part_stat_add

撰写

http://lxr.free-electrons.com/source/include/linux/genhd.h?v=4.4#L307

添加到sectors计数器......是http://lxr.free-electrons.com/source/block/blk-core.c?v=4.4#L2264

2264 void blk_account_io_completion(struct request *req, unsigned int bytes)
2265 {
2266         if (blk_do_io_stat(req)) {
2267                 const int rw = rq_data_dir(req);
2268                 struct hd_struct *part;
2269                 int cpu;
2270 
2271                 cpu = part_stat_lock();
2272                 part = req->part;
2273                 part_stat_add(cpu, part, sectors[rw], bytes >> 9);
2274                 part_stat_unlock();
2275         }
2276 }

它使用硬编码" bytes >> 9"从请求大小(以字节为单位)来计算扇区大小(或者为什么向下舍入?)或者对于人类而不是非浮点编译器计算扇区大小,它与bytes / 512相同。

还有blk_rq_sectors函数(此处未使用...)从请求获取扇区计数,从字节到扇区执行相同的>>9 http://lxr.free-electrons.com/source/include/linux/blkdev.h?v=4.4#L853

841 static inline unsigned int blk_rq_bytes(const struct request *rq)
842 {
843         return rq->__data_len;
844 }

853 static inline unsigned int blk_rq_sectors(const struct request *rq)
854 {
855         return blk_rq_bytes(rq) >> 9;
856 }

Linux中FS / VFS子系统的作者回复https://lkml.org/lkml/2015/8/17/234"内核中为什么SECTOR_SIZE = 512?" (2015):

 #define SECTOR_SHIFT 9

Theodore Ts的消息https://lkml.org/lkml/2015/8/17/269' o:

  

它是一成不变的。内核中有太多的地方,   特别是在大量的文件系统中,它们假设了   扇区大小为512字节。因此,在块层之上,扇区大小   总是512。

     

对于使用的用户空间程序,这实际上是更好   / proc / diskstats,因为他们不需要知道是否特定   底层硬件使用512,4k,(或者如果硬盘制造商   幻想成为真正的32k或64k)扇区大小。

     

由于类似的原因,struct size中的st_blocks总是以512为单位   字节。我们不想强迫用户空间必须弄清楚是否   底层文件系统使用1k,2k或4k。是因为   st_blocks的单位总是512字节,这是   在POSIX标准中硬编码。