linux下write_bytes字段表示进程向块设备实际写入的字节数,windows对应writetransfercount;二者均反映真实落盘量,不含缓存未刷数据,是跨平台磁盘io统计的权威指标。

Linux下读取/proc/[pid]/io中的write_bytes字段
Linux内核通过 /proc/[pid]/io 文件暴露进程I/O统计,其中 write_bytes 行表示该进程向块设备(如磁盘)实际写入的字节数(注意:不是write()系统调用次数或缓冲区大小,而是落盘量)。获取当前进程只需读取 /proc/self/io:
#include <fstream>
#include <string>
#include <iostream>
uint64_t get_write_bytes() {
std::ifstream io("/proc/self/io");
std::string line;
while (std::getline(io, line)) {
if (line.substr(0, 11) == "write_bytes") {
size_t pos = line.find(':');
if (pos != std::string::npos) {
try {
return std::stoull(line.substr(pos + 1));
} catch (...) {}
}
}
}
return 0;
}
</iostream></string></fstream>
常见错误:误读 writes(写调用次数)或 written(已废弃字段),这两个不反映真实落盘量;write_bytes 才是权威指标。
Windows下用GetProcessIoCounters获取WriteTransferCount
Windows需调用 GetProcessIoCounters,其返回的 IO_COUNTERS 结构中 WriteTransferCount 字段即为总写入字节数(同Linux的 write_bytes 语义):
#include <windows.h>
#include <iostream>
uint64_t get_write_bytes() {
IO_COUNTERS counters = {};
if (GetProcessIoCounters(GetCurrentProcess(), &counters)) {
return counters.WriteTransferCount;
}
return 0;
}
</iostream></windows.h>
注意点:
-
GetProcessIoCounters需要PROCESS_QUERY_INFORMATION权限,沙盒环境(如某些IDE调试器、容器)可能拒绝访问,返回0且GetLastError()为ERROR_ACCESS_DENIED - 该值包含所有写操作:文件、管道、设备驱动等,但不含网络socket发送量(那是网络栈统计)
跨平台封装时需规避的陷阱
直接拼接宏判断平台容易漏掉细节:
- Linux下
/proc/self/io在容器中可能被挂载为只读或屏蔽(如Docker默认禁用procfs的部分字段),此时读取会失败或返回0 - Windows在低完整性级别进程(如IE保护模式、UAC降权运行)中调用
GetProcessIoCounters必然失败,无法降级 fallback - 两个平台的值都**不包含缓存未刷盘的数据**——例如
write()后立即读write_bytes,若数据还在page cache里,不会计入
建议封装时显式处理失败路径,不要静默返回0,可加日志提示“IO stats unavailable: /proc/self/io inaccessible or access denied”。
为什么不能用getrusage或POSIX的clock_gettime
getrusage(RUSAGE_SELF, &ru) 中的 ru_oublock 字段在glibc中早已废弃(自2.26起标记为unimplemented),实际始终为0;而 clock_gettime(CLOCK_PROCESS_CPUTIME_ID) 只统计CPU时间,和I/O字节完全无关。试图用这些接口“凑数”会导致监控数据完全失真。
真实场景中,如果你在做资源限制或计费统计,必须依赖内核原生暴露的I/O计数器,其他任何用户态估算(比如hook write()并累加)都会漏掉mmap写、sendfile、splice等零拷贝路径。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











