目的:我希望获得iostat
命令可以获取的信息。
我已经知道,如果打开/proc/diskstats
或/sys/block/sdX/stat
,则有以下信息:扇区读取和扇区写入。所以如果我想得到读/写字节/ s,下面的公式是对的吗?
每秒读/写字节数:
(扇区读/写(现在) - 段读/写(最后))* 512字节/时间间隔每秒读/写操作:
(读/写IOs(现在)+读/写合并(现在)-read / write IOs(last)-read / write merges(last))/ time interval
因此,如果我有一个计时器,每个第二个控制软件从这两个文件中读取信息,然后使用上面的公式来计算值。可以得到正确的答案吗?
答案 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]),
结构sectors
在http://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标准中硬编码。