Linux下用/proc/stat计算总CPU负载率最可靠,需两次采样cpu行前4字段(user、nice、system、idle)的差值,计算(总时间差−空闲时间差)/总时间差,间隔200–500ms,避免单次读取或混淆iowait。

Linux下用/proc/stat计算总CPU负载率最可靠
直接读/proc/stat是Linux获取全局CPU使用率最轻量、最准确的方式。它不依赖第三方库,也不需要轮询或特权,只要能读文件就行。第一行cpu(不含后缀数字)的4个字段(user、nice、system、idle)加起来就是总ticks,用两次采样差值算出实际占用比例。
常见错误是只取一次快照——必须间隔至少100ms再读一次,否则结果恒为0;另一个坑是把idle和iowait混用,iowait不属于空闲时间,不能计入分母。
- 采样间隔建议设为200–500ms,太短误差大,太长响应滞后
- 计算公式:
(total_ticks_last - idle_ticks_last) - (total_ticks_now - idle_ticks_now)/(total_ticks_last - total_ticks_now) - 注意:
idle字段在较新内核中已包含steal和guest,无需额外处理
获取每核负载需解析cpu0、cpu1等独立行
/proc/stat里以cpu0、cpu1开头的行对应各逻辑核,字段顺序和cpu行一致。遍历这些行就能拿到每个核的原始tick数据。
容易忽略的是:逻辑核数量不等于物理核心数(超线程会翻倍),sysconf(_SC_NPROCESSORS_ONLN)返回的是当前在线逻辑核数,应以此为准动态分配数组,而非硬编码CPU_SETSIZE或猜上限。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 逐行读取时用
strncmp(line, "cpu", 3)判断,避免匹配到cpu01误判为cpu0 - 每个核的idle值要单独保存,不能复用全局
cpu行的idle - 某些嵌入式系统可能不暴露单核数据(如只有
cpu行),需做fallback处理
Windows下必须用GetSystemTimes,别碰WMI或Performance Counters
Windows没有/proc等价物,GetSystemTimes是唯一轻量、无权限、实时性好的API。它返回三个FILETIME:空闲时间、内核时间、用户时间,单位是100ns,需转为毫秒再计算。
很多人误用WMI(Win32_PerfFormattedData_PerfOS_Processor),延迟高且首次查询慢;也有人用QueryPerformanceCounter自己累加,但无法区分用户/内核/空闲,精度反而更低。
-
GetSystemTimes在Win7+可用,XP需用PDH回退,但已基本淘汰 - 返回的空闲时间是系统级总计,无法拆出单核——Windows不提供原生单核idle,只能靠
GetProcessTimes+ 多线程采样间接估算 - 注意
FILETIME是64位整数,直接减可能溢出,要用ULARGE_INTEGER结构体安全转换
C++封装时避免std::chrono精度陷阱和跨平台类型混淆
用std::chrono::steady_clock::now()做采样间隔看似方便,但在某些Linux容器或VM里,其分辨率可能只有10ms甚至更差,导致两次采样值相同,算出负载为0。更稳妥的是用clock_gettime(CLOCK_MONOTONIC, ...)(Linux)或QueryPerformanceCounter(Windows)。
跨平台封装时,别用long long存tick值——Windows的FILETIME是两个DWORD,Linux的jiffies在不同内核配置下可能是unsigned long或unsigned long long。统一用uint64_t存储归一化后的毫秒或微秒值。
- Linux采样后立刻用
clock_gettime打时间戳,别等解析完再记时 - Windows下
GetSystemTimes返回的FILETIME必须转成100ns单位再相减,直接reinterpret_cast会出错 - 输出格式建议保留小数点后一位(如
"CPU total: 42.3%"),整数显示易掩盖波动
实际部署时,最常被绕过的细节是:容器环境(Docker/K8s)中/proc/stat反映的是宿主机全局状态,不是容器限制后的CPU配额使用率;若需容器视角,得结合/sys/fs/cgroup/cpuacct/cpuacct.usage和cpu.cfs_quota_us重新归一化。

















