如何在 linux 上的编程中每秒从 /proc 获取磁盘 read/write 字节?
how to get disk read/write bytes per second from /proc in programming on linux?
目的 :我想得到像iostat
这样的信息命令可以得到。
我已经知道如果打开/proc/diskstats
或/sys/block/sdX/stat
有信息说:sectors read and sectors write。所以如果我想得到 read/write bytes/s ,下面的公式是对的 ?
read/write bytes per second:
(sectors read/write(now)-sectors read/write(last))*512 bytes/time interval
read /write operations per second :
(read/write IOs(now)+read/write merges(now)-read/write IOs(last)-read/write merges(last ))/time interval
所以如果我有一个计时器,控制软件每秒从这两个文件中读取信息,然后使用上面的公式计算该值。我能得到正确答案吗?
TLDR扇区为512字节(octets;1个扇区为512字节;每个字节为8位;每位为0或1,但不能叠加其中)。
"The standard sector size of 512 bytes for magnetic disks was established ....[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,
因此,读取扇区计数并除以二得到 kilobyte/s(好像 1 个扇区读取是 0.5 kb 读取;2 个扇区读取是 1 kb 读取等等)。我们可以得出结论,扇区总是 512 字节。文档中也有说明,不是吗?:
互联网搜索“/proc/diskstats”->
https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats ->
https://www.kernel.org/doc/Documentation/iostats.txt "I/O statistics fields" 来自美国 ibm 的 ricklind
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 "Why is SECTOR_SIZE = 512 inside kernel ?" (2015) 时说:
#define SECTOR_SHIFT 9
Theodore Ts'o 的留言 https://lkml.org/lkml/2015/8/17/269:
It's cast in stone. There are too many places all over the kernel,
especially in a huge number of file systems, which assume that the
sector size is 512 bytes. So above the block layer, the sector size
is always going to be 512.
This is actually better for user space programs using
/proc/diskstats, since they don't need to know whether a particular
underlying hardware is using 512, 4k, (or if the HDD manufacturers
fantasies become true 32k or 64k) sector sizes.
For similar reason, st_blocks in struct size is always in units of 512
bytes. We don't want to force userspace to have to figure out whether
the underlying file system is using 1k, 2k, or 4k. For that reason
the units of st_blocks is always going to be 512 bytes, and this is
hard-coded in the POSIX standard.
目的 :我想得到像iostat
这样的信息命令可以得到。
我已经知道如果打开/proc/diskstats
或/sys/block/sdX/stat
有信息说:sectors read and sectors write。所以如果我想得到 read/write bytes/s ,下面的公式是对的 ?
read/write bytes per second:
(sectors read/write(now)-sectors read/write(last))*512 bytes/time intervalread /write operations per second :
(read/write IOs(now)+read/write merges(now)-read/write IOs(last)-read/write merges(last ))/time interval
所以如果我有一个计时器,控制软件每秒从这两个文件中读取信息,然后使用上面的公式计算该值。我能得到正确答案吗?
TLDR扇区为512字节(octets;1个扇区为512字节;每个字节为8位;每位为0或1,但不能叠加其中)。
"The standard sector size of 512 bytes for magnetic disks was established ....[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,
因此,读取扇区计数并除以二得到 kilobyte/s(好像 1 个扇区读取是 0.5 kb 读取;2 个扇区读取是 1 kb 读取等等)。我们可以得出结论,扇区总是 512 字节。文档中也有说明,不是吗?:
互联网搜索“/proc/diskstats”->
https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats ->
https://www.kernel.org/doc/Documentation/iostats.txt "I/O statistics fields" 来自美国 ibm 的 ricklind
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 "Why is SECTOR_SIZE = 512 inside kernel ?" (2015) 时说:
#define SECTOR_SHIFT 9
Theodore Ts'o 的留言 https://lkml.org/lkml/2015/8/17/269:
It's cast in stone. There are too many places all over the kernel, especially in a huge number of file systems, which assume that the sector size is 512 bytes. So above the block layer, the sector size is always going to be 512.
This is actually better for user space programs using /proc/diskstats, since they don't need to know whether a particular underlying hardware is using 512, 4k, (or if the HDD manufacturers fantasies become true 32k or 64k) sector sizes.
For similar reason, st_blocks in struct size is always in units of 512 bytes. We don't want to force userspace to have to figure out whether the underlying file system is using 1k, 2k, or 4k. For that reason the units of st_blocks is always going to be 512 bytes, and this is hard-coded in the POSIX standard.