跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

c++怎么解析Linux系统的/proc虚拟文件_读取CPU和内存状态【实战】

直接读/proc/stat和/proc/meminfo即可,用std::ifstream逐行解析,注意jiffies差值计算CPU使用率、kB单位为十进制、优先用MemAvailable并处理内核版本差异。 直接读
/proc/stat
和
/proc/meminfo
就行,别碰 syscall 或第三方库 Linux 的
/proc
是内核吐出的纯文本接口,C++ 读它跟读普通文件完全一样——用
std::ifstream
或
fopen
即可。没人需要 syscall、
libprocps
或
sysfsutils
,那些是给系统工具(如
top
)封装用的,你写监控脚本或轻量采集器,直接 parse 文本最稳。 常见错误是试图用
stat()
检查
/proc/pid/status
是否存在来“判断进程存活”,结果发现刚 fork 出来的进程还没来得及注册进
/proc
,
stat()
就返回失败——这不是 bug,是
/proc
的天然竞态。真要查进程,要么重试几次,要么改用
kill(pid, 0)
。
/proc/stat
里第一行
cpu
后面的数字是各 CPU 模式下的 jiffies(非毫秒!),需两次采样做差再换算
/proc/meminfo
的值单位统一是
kB
(注意不是 KB),
MemTotal:
和
MemAvailable:
是关键字段 别用
std::getline
无脑读整行再
find("MemFree:")
——有些发行版(如 RHEL 8+)默认关闭
MemFree
,只留
MemAvailable
,必须兼容
std::ifstream
读
/proc
文件时,必须检查
failbit
而非只看 EOF
/proc
文件不是磁盘文件,读取过程可能被内核中断(比如 CPU 热插拔导致
/proc/stat
行数突变),
std::ifstream
容易静默失败:流状态变成
failbit
,但你没检查就继续
>>
,变量值还是旧的,结果 CPU 使用率卡在 0%。 每次
operator>>
后立刻检查
if (!ifs) { /* handle error */ }
,不能只靠
eof()
推荐用
std::string line
+
std::getline()
逐行读,再用
absl::StartsWith(line, "cpu ")
(或手写
line.substr(0, 4) == "cpu "
)匹配,避免
>>
把空格当分隔符吃掉字段 读
/proc/meminfo
时,某行可能是
MemAvailable: 123456 kB
,中间多个空格,别用
>>
直接读三个变量,会错位;先
find_first_of(':')
切割键值,再
stoll
转数字 计算 CPU 使用率必须采样两次,且间隔 ≥100ms 单次读
/proc/stat
只能拿到累计 jiffies,没法算使用率。核心逻辑是:记录两次时间戳和对应的
user
、
system
、
idle
、
iowait
值,求差值后按比例折算——但很多人忽略两个硬约束: 立即学习 “ C++免费学习笔记(深入) ”; C知道 CSDN推出的一款AI技术问答工具 下载 两次采样间隔太短(如 10ms),jiffies 差值可能为 0(尤其空闲机器),导致除零或结果跳变 别用
std::chrono::steady_clock::now()
算耗时然后除以 1e9 得秒数——jiffies 是内核滴答,和 wall-clock 不严格线性对应;只要两次间隔 ≥100ms,误差可接受 公式里分母是所有模式 jiffies 总和的差值(
user + system + idle + iowait + ...
),不是只用
user + system
;漏掉
idle
会导致使用率虚高 示例片段:
long long total_jiffies_diff = (user2 + nice2 + system2 + idle2 + iowait2) - (user1 + nice1 + system1 + idle1 + iowait1);
double cpu_usage = 100.0 * (total_jiffies_diff - (idle2 - idle1)) / total_jiffies_diff;
内存单位陷阱:
/proc/meminfo
的
kB
是千字节,不是 KiB 文档写的是 “kB”,实际值是十进制千字节(1000 字节),不是二进制 KiB(1024 字节)。虽然误差仅 2.4%,但如果你拿这个值去和
sysconf(_SC_PAGESIZE)
算页数,或者和
getrusage()
返回的字节数对比,就会对不上。
MemTotal:
是物理内存总大小(含保留区),
MemAvailable:
是内核估算的、可立即分配给用户进程的内存,比
MemFree + Buffers + Cached
更准,优先用它 某些嵌入式 kernel(如 Android 的 vendor kernel)可能不提供
MemAvailable
,此时 fallback 到
MemFree + Buffers + Cached - SReclaimable
,但要注意
SReclaimable
是 slab 中可回收部分,不是所有
Cached
都能动 别把
/proc/meminfo
当唯一依据——OOM killer 触发前,
MemAvailable
可能还有几百 MB,但具体到某个进程,
malloc()
仍会失败,因为内存碎片或 cgroup 限额已满 真实环境里,
/proc
解析最难的不是语法,是应对内核版本差异和容器化带来的字段漂移——比如
cgroups v2
下,
/proc/1/status
的
CapEff:
可能被截断,
/proc/mounts
里看不到 cgroup mount 信息。这些没法靠“标准做法”解决,只能根据目标环境实测校验。

相关文章