read_bytes是唯一反映进程真实磁盘读取总量的字段,仅统计实际从块设备读入内存的字节数,不含缓存命中或伪设备读取;多次采样其差值即为某时段真实磁盘读量。

Linux下读取/proc/pid/io里的read_bytes字段
Linux内核通过/proc/[pid]/io文件暴露进程I/O统计,其中read_bytes行记录了该进程自启动以来从块设备读取的字节数(不含缓存命中)。这是最直接、开销最低的方式。
实操要点:
- 需用
getpid()获取当前进程PID,拼出路径如/proc/12345/io - 逐行读取文件,匹配以
read_bytes:开头的行,提取后跟的十进制整数 - 注意:该值是累加值,不是瞬时速率;若需速率,需两次采样做差并除以时间间隔
- 权限无特殊要求——只要进程存在,当前用户就能读自己的
/proc/pid/io
示例片段:
#include <fstream>
#include <string>
#include <unistd.h>
long long get_read_bytes() {
std::string path = "/proc/" + std::to_string(getpid()) + "/io";
std::ifstream f(path);
std::string line;
while (std::getline(f, line)) {
if (line.substr(0, 11) == "read_bytes:") {
return std::stoll(line.substr(11));
}
}
return -1; // 未找到
}</unistd.h></string></fstream>
Windows下用GetProcessIoCounters获取ReadTransferCount
Windows没有统一的“磁盘读取字节”概念,GetProcessIoCounters返回的ReadTransferCount字段最接近——它表示该进程所有线程在句柄上执行的读操作传输的总字节数(含文件、管道、设备等,不限于物理磁盘)。
关键限制:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 该值包含缓存读取(如
ReadFile从page cache读)、网络重定向(如UNC路径)、甚至内存映射文件的首次页入 - 无法区分是否真正触发了磁盘IO;若想过滤纯磁盘行为,需结合ETW或WMI,但代价高得多
- 调用前必须用
GetCurrentProcess()获取句柄,并确保有PROCESS_QUERY_INFORMATION权限(通常默认具备)
示例片段:
#include <windows.h>
long long get_read_bytes_win() {
IO_COUNTERS io{};
if (GetProcessIoCounters(GetCurrentProcess(), &io)) {
return static_cast<long long>(io.ReadTransferCount);
}
return -1;
}</long></windows.h>
跨平台封装时要注意的陷阱
别试图用同一套逻辑抽象Linux和Windows——二者语义差异太大。常见误用:
- 把Windows的
ReadTransferCount当作Linux的read_bytes等价指标,忽略其包含非磁盘IO的现实 - 在Linux下误读
rchar(所有read系统调用字节数,含pipe/socket)而非read_bytes - 没处理
/proc/pid/io文件可能因进程退出而瞬间消失,导致open失败 - 忽略大数值:两个平台都可能超
int64_t范围,务必用long long或uint64_t
为什么不用perf_event_open或sysfs?
有人会想到用Linux的perf_event_open监控PERF_COUNT_SW_PAGE_FAULTS之类,或查/sys/fs/cgroup/.../io.stat——这些要么需要root权限,要么属于cgroup层级统计(非单进程),要么粒度太粗(如按设备汇总)。对单进程磁盘读字节的干净需求,/proc/pid/io仍是唯一无需特权、精确到进程、且被广泛支持的方案。
实际写代码时,最容易漏掉的是Linux路径拼接后没检查文件是否存在,以及Windows下忘记链接Advapi32.lib导致链接失败——这两个点卡住的人比想象中多。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










