Linux 通过 /proc/self/io 获取 read_bytes 和 write_bytes 字节数,Windows 调用 GetProcessIoCounters 获取 ReadTransferCount 和 WriteTransferCount,macOS 无可靠字节级统计接口,需降级或依赖外部工具。

Linux 下读取 /proc/self/io 获取进程 I/O 统计
Linux 内核通过 /proc/[pid]/io(对当前进程即 /proc/self/io)暴露了精确的累计磁盘读写字节数,这是最直接、无额外权限依赖的方式。该文件每行是 key: value 格式,关键字段为 read_bytes 和 write_bytes —— 它们统计的是实际发往底层块设备的字节数(不包含缓存命中),单位是字节。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
std::ifstream打开/proc/self/io,逐行读取并按冒号分割,跳过空行和注释行 - 注意
read_bytes和write_bytes的值可能极大(如 TB 级),务必用unsigned long long解析 - 若读取失败(如文件不存在或权限不足),返回 0 或抛异常;
/proc在容器中通常可用,但某些极简运行时(如 gVisor)可能不支持 - 示例关键逻辑:
std::ifstream io("/proc/self/io"); std::string line; while (std::getline(io, line)) { if (line.rfind("read_bytes:", 0) == 0) { auto val = std::stoull(line.substr(11)); } else if (line.rfind("write_bytes:", 0) == 0) { auto val = std::stoull(line.substr(12)); } }
Windows 下调用 GetProcessIoCounters 获取 I/O 总量
Windows 没有等价的伪文件系统接口,必须调用 Win32 API:GetProcessIoCounters。它返回 IO_COUNTERS 结构体,其中 ReadTransferCount 和 WriteTransferCount 即为累计字节数(注意不是 ReadOperationCount 等操作次数)。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 需包含
<windows.h></windows.h>,链接kernel32.lib(MSVC 默认链接) - 传入当前进程句柄:
GetCurrentProcess(),该句柄无需额外权限 - 结构体字段是
ULONGLONG,与 Linux 的unsigned long long对应,可直接跨平台 typedef - 若函数返回
FALSE,用GetLastError()判断错误(常见于沙盒环境或权限受限进程) - 示例调用:
IO_COUNTERS io; if (GetProcessIoCounters(GetCurrentProcess(), &io)) { auto read_bytes = io.ReadTransferCount; auto write_bytes = io.WriteTransferCount; }
macOS / BSD 系统没有直接等效接口,需绕行
macOS 不提供 per-process 磁盘字节级累计统计的公开 API。libproc 的 proc_pidinfo 只能拿到读写操作次数(PROC_PIDIOCOUNTERS),没有字节数;sysctl 的 kern.boottime 等全局指标也无帮助。
可行替代方案(有明显局限):
- 用
task_info+TASK_IO_INFO(仅 macOS):返回task_io_t,含bytes_read和bytes_written,但**仅在进程启动后首次调用时有效,后续调用返回 0** —— Apple 明确标注为“deprecated”,且实际行为不稳定 - 依赖外部工具:调用
iotop -p $$或解析ps -o pid,rbytes,wbytes输出,但需 shell 环境、权限,且精度低(ps 的 rbytes/wbytes 是估算值,非真实磁盘传输量) - 结论:若必须支持 macOS,建议降级为记录操作次数(
readv/writev调用计数),或明确文档说明该平台不支持字节级统计
跨平台封装时注意字段语义差异
Linux 的 read_bytes 和 Windows 的 ReadTransferCount 都指“成功传递给存储驱动的字节数”,语义一致;但容易忽略两点:
-
/proc/self/io中的cancelled_write_bytes表示被截断的写入(如truncate),不应从write_bytes中减去——它只是调试参考,不是已写入量的修正项 - Windows 的
OtherTransferCount包含控制操作(如ioctl)数据量,不属于磁盘读写,不要混入统计 - 所有平台均不区分“读缓存命中”和“读磁盘”,统计的是最终落盘/发往设备的量;若需缓存层分析,需用 eBPF(Linux)或 ETW(Windows)等更底层机制
真正难的是 macOS 的缺失和容器中 /proc 的挂载一致性——别假设 /proc/self/io 总存在,尤其在 rootless Docker 或 Podman 中,得加 fallback 判断。


















