Linux下需通过/proc/stat计算总CPU负载比例:读取cpu行的user、nice、system、idle、iowait、irq、softirq等字段,用非空闲时间除以总时间得出负载比例。

Linux下用/proc/stat计算总CPU负载比例
Linux没有直接返回“总CPU负载百分比”的系统调用,必须自己算。核心思路是读取/proc/stat中cpu这一行(不是cpu0等具体核),提取user、nice、、<code>idle、iowait、irq、softirq这7个字段,它们共同构成CPU时间总和。负载比例 = (total - idle) / total × 100%,其中total = user + nice + system + idle + iowait + irq + softirq。
注意:单次读取只能得到快照,必须两次采样做差值才能得到真实负载。间隔建议至少100ms,太短误差大,太长响应滞后。
- 每次读取后要跳过前缀
cpu(带空格),再按空格分割字段 -
idle包含idle和steal之后的字段,但标准cpu行只有7个字段;若内核较新(≥2.6.33),第8/9字段是steal和guest,此时idle仍是第4个字段,别数错位置 - 字段值为
unsigned long long,务必用%llu或std::stoull()解析,用int会溢出
Windows下用GetSystemTimes()获取总体CPU占用
Windows提供GetSystemTimes(),它返回三个FILETIME:空闲时间、内核时间(含空闲)、用户时间。总CPU时间 = 内核时间 + 用户时间;实际工作时间 = 总时间 − 空闲时间;负载比例 = (总时间 - 空闲时间) / 总时间 × 100%。
关键点:该函数仅从Windows Vista起可用,XP不支持;且需启用SE_INCREASE_QUOTA_NAME权限(通常进程默认有),否则返回FALSE并GetLastError()为ERROR_ACCESS_DENIED。
立即学习“C++免费学习笔记(深入)”;
- 两次调用间隔建议≥100ms,和Linux一致
-
FILETIME是100纳秒单位,转成毫秒要除以10000,转成秒要除以10000000 - 不要直接用
GetTickCount64()替代——它只返回系统启动时间,无法分离空闲/工作时间
跨平台封装时为什么不能简单平均多核数据
有人试图读取/proc/stat里所有cpu0、cpu1…再求平均,这是错的。因为cpu行本身已代表所有CPU的累加值,重复平均会导致数值失真。同理,Windows的GetSystemTimes()返回的就是全局视图,无需遍历逻辑处理器。
真正需要区分单核/多核场景的是性能分析(如定位热点核),而非总负载统计。如果你看到监控工具显示“CPU usage 85%”,它几乎肯定来自cpu行或GetSystemTimes(),而不是各核平均。
- Linux下
top、htop底层都读/proc/stat的cpu行 - Windows任务管理器的“CPU”图表也基于
GetSystemTimes() - 误用单核数据算总负载,在4核机器上可能把40%真实负载报成10%,尤其在负载不均衡时偏差更大
常见错误:采样时机不当导致结果为0或100%
最常踩的坑是两次采样时间太近(比如只sleep(1)毫秒),/proc/stat或GetSystemTimes()返回的值几乎没变,差值为0,算出来就是0%;或者因系统调度抖动,某次采样恰好卡在长空闲段,导致差值突变,算出接近100%的假峰值。
- 推荐最小采样间隔设为
100ms,用std::this_thread::sleep_for(std::chrono::milliseconds(100)) - 避免在程序刚启动时立即采样——内核统计可能尚未稳定
- 如果需要高频率更新(如每秒多次),应维护滑动窗口(如最近5次采样滚动平均),而不是单次差值硬算
真正的难点不在读数据,而在理解“负载”本质是时间占比,必须靠差值体现变化;静态快照毫无意义。很多库封装了这个逻辑,但一旦你得自己写,漏掉时间差或字段解析错一位,结果就完全不可信。


















