/sys/block/sdx/stat 的第1列(reads completed)和第5列(writes completed)是设备层确认完成的读写扇区总数,单位为逻辑扇区(通常512字节),累计值需两次采样相减得实时速率,最接近物理扇区级真实i/o量。

Linux 没有命令能直接“查看某次读写落在哪个物理扇区”,但你可以查到内核提交到设备的物理 I/O 请求统计,以及设备实际完成的扇区级操作量——这是最接近“物理扇区读写情况”的可观测指标。
看设备层真实完成的读写扇区数
关键路径是 /sys/block/sdX/stat(或 /sys/block/nvme0n1/stat),它由内核 block layer 维护,反映设备驱动确认完成的真实扇区操作,不经过 page cache,也不被合并。
- 第 1 列(reads completed):设备完成的读请求总扇区数(单位:逻辑扇区,通常是 512 字节)
- 第 5 列(writes completed):设备完成的写请求总扇区数
- 注意:这个值是累计值,不是速率;要算实时,需两次采样后相减
- 例如:
cat /sys/block/sda/stat | awk '{print $1, $5}'输出1234567 890123,说明该设备至今完成了约 123 万读扇区、89 万写扇区
iostat -dx 里的 r_ios/w_ios 是什么
iostat -dx 1 中的 r_ios 和 w_ios 表示内核提交到 block queue 的 I/O 请求次数(不是扇区数),但它比 r/s 更接近物理层——因为已绕过上层合并逻辑。
- 它不等于
/sys/block/sdX/stat的第 1/5 列,因为驱动可能把多个 request 合并成一个底层 command(尤其 NVMe 多队列) - 如果你关心“每秒多少次 4K 随机写”,盯
w_ios比wkB/s准确得多 - 常见误判:看到
wkB/s = 4096就以为是 1 次 4K 写,其实可能是 1 次 4M 连续写拆成 1000 个 request,w_ios才是 1000
为什么不能用 iotop 或 pidstat 查物理扇区
iotop 显示的是进程调用 read(2)/write(2) 的字节数,走 page cache,完全不反映物理扇区行为;pidstat -d 的 read_bytes/write_bytes 虽然来自 /proc/[pid]/io,但仍属于 VFS 层计数,无法映射到具体 LBA。
- 例如:一个进程写 4K,如果 page cache 命中且未回写,
iotop会显示 4K,但磁盘零扇区没动 - 再如:ext4 启用 delayed allocation 时,
write(2)返回成功 ≠ 数据已落盘,pidstat计数和物理扇区完全脱钩 - 真正想关联进程和物理扇区?目前无通用方案。只有在 ext4 + debugfs + block dump 场景下可手工追溯,且仅限同步写+无缓存场景
别信 fdisk -l 里的 “I/O size (minimum/optimal)”
这个值只是队列建议,不是物理扇区读写粒度。它影响的是内核 IO 调度器的行为,而非实际硬件擦写单元。
-
I/O size (minimum/optimal): 4096 bytes不代表每次读写都按 4096 扇区发出,只是说“对齐到 4096 字节边界效率最高” - 实际发出的 request 大小由上层决定(比如 dd bs=512、fio --bs=4k),
/sys/block/sdX/stat第 1/5 列才记录最终落到设备上的扇区总数 - 混淆这点会导致误判性能瓶颈:看到
w_ios很高但wkB/s很低,其实是大量小 request,而不是“物理扇区写得太慢”
真正难的不是查数字,而是理解每一层抽象的意义:VFS 层的字节 ≠ page cache 层的页 ≠ block layer 的 request ≠ 设备驱动的 command ≠ NAND/磁道上的物理扇区。跨层强行映射,99% 的时候只会得到误导性结果。











