/proc/diskstats是linux获取实时磁盘i/o数据最可靠方式,每行对应块设备,第4列(读完成次数)、第5列(读扇区数×512=字节数)、第8列(写完成次数)、第9列(写扇区数×512=字节数)为核心指标,需过滤设备名(如sda而非sda1)并确保字段数≥11以准确解析。

Linux下用/proc/diskstats读取实时磁盘I/O数据
Linux没有统一的API函数能直接返回“当前I/O状态”,最可靠的方式是解析/proc/diskstats。它每行对应一个块设备(如sda、nvme0n1),字段含义固定:第4列是读完成次数,第8列是写完成次数,第5/9列分别是读/写字节数(需×512换算为字节)。
实操建议:
- 用
std::ifstream打开/proc/diskstats,逐行std::getline解析,跳过空行和注释行 - 按空格分割后检查字段数≥11,再取索引3、4、7、8(0起始)——避免因设备名含空格(如
dm-0)导致错位 - 注意:同一设备可能有多个条目(如
sda和sda1),若要汇总物理盘数据,只统计无数字后缀的设备名(正则^[a-z]+[0-9]*$不匹配sda1) - 两次采样间隔建议≥100ms,否则
delta易为0;短时间高频读取不会显著影响性能,但/proc是内存虚拟文件,无磁盘IO开销
Windows下用PdhAddCounter获取磁盘计数器
Windows必须走PDH(Performance Data Helper)接口,不能靠GetDiskFreeSpaceEx这类函数——它只返回容量,不反映实时I/O负载。
关键点:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 计数器路径格式为
\PhysicalDisk(_Total)\Disk Reads/sec,_Total汇总所有磁盘;若要单盘,用\PhysicalDisk(0 C:)\...,其中0 C:需通过SetupDiEnumDeviceInterfaces查真实实例名 - 必须先调
PdhOpenQuery,再PdhAddCounter,最后PdhCollectQueryData触发采集;首次调用返回PDH_INVALID_DATA属正常,需等待至少一次完整采集周期(通常1s) - 别用
PdhGetFormattedCounterValue直接转double——它会四舍五入丢失小数精度;应改用PdhGetRawCounterValue取PDH_RAW_COUNTER,再手动计算(公式见MSDN) - 权限问题:普通用户可读大部分磁盘计数器,但某些驱动级指标(如
Avg. Disk Queue Length)需管理员权限,否则PdhAddCounter返回PDH_ACCESS_DENIED
C++跨平台封装时为什么不能依赖statvfs或GetDriveType
statvfs(POSIX)和GetDriveType(Windows)只告诉你“磁盘是否存在”“是否可写”“剩余空间多少”,完全不提供I/O活动信息。试图用它们推导I/O状态属于典型误用。
常见错误现象:
- 轮询
statvfs发现f_bfree在变,就认为“正在写入”——错。缓存延迟、预分配、日志刷盘都会导致空间变化与实际I/O脱节 - 检测到
GetDriveType返回DRIVE_FIXED就硬编码成“本地SSD”,然后假定I/O延迟 - 在容器环境(如Docker)里读
/proc/diskstats,拿到的是宿主机设备数据,而非容器cgroup限速后的实际可用I/O带宽
性能监控场景下iostat -x 1输出字段如何映射到代码逻辑
调试时对比iostat -x 1能快速验证你的解析是否正确。重点关注三组字段:
-
r/s和w/s→ 对应/proc/diskstats第4列(读完成)和第8列(写完成)的每秒增量 -
rkB/s和wkB/s→ 对应第5列(读扇区数)×512÷1024 和 第9列(写扇区数)×512÷1024 -
%util→ 不是CPU利用率!是设备忙时百分比,需用io_ticks / (sample_time_ms × 1000)计算(io_ticks是/proc/diskstats第10列,单位是毫秒)
容易被忽略的是:Linux 5.0+内核中io_ticks已改为纳秒级,但iostat仍按旧逻辑除1000处理;你的代码若运行在新内核,需检查/proc/version并动态调整分母。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










