需两次采样/proc/diskstats取第6列扇区数差值,乘512换算为字节,再除以时间间隔;须匹配主设备行(如sda而非sda1),字段提取应跳过空白逐域解析,避免空格分割错位。

Linux 下用 /proc/diskstats 计算每秒磁盘读取字节数
直接读 /proc/diskstats 是最轻量、最可靠的方式,无需 root 权限,也不依赖外部工具。该文件第 6 列(从 0 开始计数)是该设备累计读取的扇区数(512 字节/扇区),用两次采样差值就能算出每秒读取字节数。
注意:不是所有行都代表物理磁盘——要过滤掉分区行(如 sda1、nvme0n1p2),只保留主设备(sda、nvme0n1),否则会重复累加。设备名需从 /sys/block/*/device 或内核命名规则判断,但简单起见,可先硬编码关注的设备(如 "sda" 或 "nvme0n1")。
示例逻辑:
// 伪代码示意,实际需 parse /proc/diskstats 行 std::string device = "sda"; int sector_col = 5; // 第6列(0-indexed) long long read_sectors_now = parse_diskstats(device, sector_col); long long delta_sectors = read_sectors_now - last_sectors; long long bytes_per_sec = delta_sectors * 512 / interval_sec;
C++ 中解析 /proc/diskstats 的常见错误
最容易踩的坑是字段对齐错位:不同内核版本中,/proc/diskstats 行字段数可能为 14 或 20(含 NVMe 队列深度等扩展字段),但前 14 列含义固定。不能按空格 split 后取第 6 个 token——因为设备名里可能含空格(极少见)或字段本身为空(如未启用的设备),应使用 std::istringstream 跳过前导空白并逐字段提取,确保取到的是第 6 个有效数字字段。
其他要点:
将提醒同步至 Windows/Outlook 日历。用户提及「提醒我」「设置提醒」「加到日历」「同步到日历」「日程」「calendar」「日历」时触发。支持Microsoft Graph API 设备代码流认证,无需 Web 服务器,直接写入用户 Outlook 日历。
- 每次读取必须重新打开并完整扫描文件,不能 fseek 复用 fd —— 内核会动态生成内容,fd 不支持随机读
- 避免在循环中频繁 new/delete 字符串;用栈上
std::array<char></char>+read()更稳 - 设备名匹配要用
starts_with(C++20)或strncmp,防止sda匹配到sda1 - 若程序运行时设备热插拔,
/proc/diskstats可能临时缺失某行,需容忍解析失败
Windows 下用 PdhAddCounter 获取磁盘读取字节数/秒
Windows 没有类 Unix 的 procfs,得走 PDH(Performance Data Helper)API。对应计数器是 "\PhysicalDisk(_Total)\Disk Read Bytes/sec" 或指定实例(如 "\PhysicalDisk(0 C:)\Disk Read Bytes/sec")。注意:这不是“累计值”,而是系统已计算好的每秒速率,直接取值即可,无需差分。
关键限制:
- 首次调用
PdhOpenQuery后必须调用PdhCollectQueryData至少两次(间隔 ≥1 秒),第二次才返回有效数值;第一次永远是 0 或无效 - 计数器路径中的实例名(如
0 C:)需通过PdhEnumObjectItems动态枚举,硬编码极易失效(尤其在多磁盘或存储池环境下) -
PdhGetFormattedCounterValue返回类型是PDH_FMT_LONG或PDH_FMT_DOUBLE,取决于 Windows 版本和驱动,建议统一用PDH_FMT_DOUBLE并检查dwType字段 - PDH 句柄需手动
PdhCloseQuery,否则资源泄漏(不是 RAII 友好型 API)
跨平台封装时绕不开的细节差异
Linux 和 Windows 的语义根本不同:Linux 给你原始累计扇区,你控制采样间隔、做差分、自己处理溢出;Windows 给你瞬时速率,但受制于 PDH 刷新周期(默认 1 秒)和驱动实现,可能滞后或平滑。两者结果无法直接比对。
若封装成统一接口,必须明确约定:
- 返回值单位统一为
bytes_per_second(double 类型),不暴露底层“累计”或“瞬时”概念 - 最小采样间隔设为 1 秒;小于该值在 Linux 下精度崩坏,在 Windows 下强制等待
- 错误处理策略一致:Linux 下
/proc/diskstats不可读 → 返回 0;Windows 下 PDH 查询失败 → 返回 NaN 或抛异常(由调用方决定) - 不尝试自动识别“当前程序所用磁盘”——C++ 无标准方式将文件描述符映射回块设备,
/proc/self/fd/只能查到挂载点,无法反推底层 disk
真正难的从来不是读数据,而是定义清楚“当前程序的磁盘读取”到底指什么:是进程所有线程的 I/O?是否包含 page cache 命中?是否统计 direct I/O?这些边界问题不厘清,数值再准也没意义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










