linux下c++读取/proc/pid/io获取原始io统计的唯一可靠方式是直接解析该文件,提取read_bytes等字段计算差值与时间间隔之比得到瞬时速率,需注意权限、进程存在性、字段解析健壮性及异常处理。

Linux下C++读取/proc/pid/io获取原始IO统计
直接读/proc/[pid]/io是唯一可靠方式,它提供内核维护的累计字节数,不是瞬时速率。你需要两次采样做差值再除以时间间隔。注意该文件每行格式为key: value,其中rchar(应用层读取字节数)、read_bytes(实际物理读取字节数)最常用——前者含缓存命中,后者才是真正磁盘IO。
常见错误是误读syscr/syscw(系统调用次数),它们和吞吐量无关;还有人把wchar当写入速率,但write_bytes才是真实写入量。
- 必须以目标进程有效UID运行,否则
/proc/[pid]/io返回空或Permission denied -
pid需存在且未退出,建议先检查/proc/[pid]/stat是否存在 - 字段顺序固定,但不同内核版本可能新增字段,应按冒号分割并跳过空行,不依赖行号
用std::ifstream解析io文件并提取read_bytes
别用C风格fscanf,容易因空格/制表符错位。C++推荐逐行读+std::string::find定位冒号,再用std::stoll转数值。关键点:字段名后有空格,read_bytes:实际是"read_bytes: ",所以查找时要带冒号和空格。
std::ifstream io_file("/proc/" + std::to_string(pid) + "/io");
std::string line;
long long read_bytes = 0;
while (std::getline(io_file, line)) {
size_t pos = line.find("read_bytes: ");
if (pos != std::string::npos) {
try {
read_bytes = std::stoll(line.substr(pos + 12));
} catch (...) { }
break;
}
}
注意std::stoll可能抛异常(如空字符串),务必包裹try/catch;substr偏移量12来自"read_bytes: "长度,硬编码更安全,避免trim引入额外开销。
计算瞬时IO速率需两次采样+时间差
单次读取只有累计值,速率=(第二次read_bytes − 第一次read_bytes)/ 时间差(秒)。时间差用std::chrono::steady_clock,别用time()——后者可能受系统时间调整影响。
- 采样间隔至少100ms,太短会导致除零或噪声过大
- 若两次采样间进程退出,第二次读
/proc/pid/io失败,应返回-1或跳过计算 - 结果单位是字节/秒,通常需除以1024.0转KB/s,再除1024.0转MB/s,注意用浮点除法
示例:第一次得read_bytes=5242880,1秒后得10485760,则速率为(10485760 - 5242880) / 1.0 = 5242880.0 B/s ≈ 5.0 MB/s。
权限不足或路径不存在时的fallback处理
普通用户无法读取其他用户的/proc/pid/io,会触发std::ifstream::fail()。此时不要静默忽略,应明确区分三种情况:
-
/proc/[pid]不存在 → 进程已终止 -
/proc/[pid]/io打开失败但/proc/[pid]存在 → 权限不足(需sudo或同用户运行) - 文件可读但无
read_bytes行 → 内核版本过低(/proc/pid/io从2.6.20起支持)
实际部署时,建议先用access("/proc/[pid]/io", R_OK)预检权限,比盲目打开再判断更轻量;对root进程,普通用户永远读不到,这点无法绕过。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











