TLDR 扇区为 512 字节(octets;1 个扇区为 512 字节;每个字节为 8 位;每个位为 0 或 1,但不能叠加)。
“磁盘的标准扇区大小为 512 字节已建立....[可疑 – 讨论]” (c) wiki 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.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美国 ibm 的 ricklind 的“I/O 统计字段”
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'o 的消息https://lkml.org/lkml/2015/8/17/269:
它是一成不变的。整个内核的地方太多了,
尤其是在大量文件系统中,它们假设
扇区大小为 512 字节。所以在块层之上,扇区大小
永远是 512。
这实际上更好用户空间程序使用
/proc/diskstats,因为它们不需要知道某个特定的
底层硬件使用 512、4k(或者如果 HDD 制造商
幻想变成了真正的 32k 或 64k) 扇区大小。
出于类似的原因,st_blocks 的结构大小总是以 512 为单位
字节。我们不想强迫用户空间必须弄清楚是否
底层文件系统使用 1k、2k 或 4k。是因为
st_blocks 的单位总是 512 字节,这是
在 POSIX 标准中硬编码。