最可靠方式是linux用/proc/stat、windows用getsystemtimes;需两次采样计算差值,注意idle与iowait均为空闲时间,分母为总时间,跨平台需统一采样间隔并用uint64_t防截断。

Linux下用/proc/stat计算CPU占用率最可靠
直接读/proc/stat是Linux上获取整体CPU使用率最轻量、最标准的方式。它不依赖外部工具或复杂库,也不需要root权限,只要能读取该文件即可。
关键点在于:第一行cpu是所有CPU核心的累加值,包含user、nice、system、idle、iowait、irq、softirq等字段。真实占用率 = 1 - (idle2 - idle1) / (total2 - total1),其中total = user + nice + system + idle + iowait + irq + softirq。
- 必须做两次采样(间隔如200ms以上),单次读取无法得出占用率
-
idle和iowait都算空闲时间,漏掉iowait会导致高估占用(尤其I/O繁忙时) - 注意字段顺序可能因内核版本略有差异,建议按名称解析而非硬编码索引
- 示例片段:
std::ifstream f("/proc/stat");<br>std::string line;<br>std::getline(f, line);<br>// 解析"cpu 123 45 67 890 ..."中的各数值
Windows下用GetSystemTimes避免WMI开销
在Windows上,别一上来就用WMI或PowerShell——它们启动慢、权限要求高、容易超时。GetSystemTimes是WinAPI提供的轻量接口,返回三个FILETIME:空闲时间、内核时间(含idle)、用户时间。占用率 = 1 - (idle2 - idle1) / ((kernel2 + user2) - (kernel1 + user1))。
- 该函数从Windows XP起可用,但需链接
kernel32.lib - 返回的
FILETIME是100纳秒单位,要转成毫秒再做减法,否则整数溢出风险高 - 注意:
GetSystemTimes在某些虚拟机或旧版WSL中可能返回FALSE,需检查返回值并降级处理 - 不要用
GetTickCount64来算时间差——它只提供系统运行时间,不含CPU时间维度
C++跨平台封装要注意采样时机和精度陷阱
写一个跨平台的get_cpu_usage()函数时,最容易翻车的是时间控制和类型转换。不是“调一次API就能出结果”,而是必须管理状态:上次采样的时间戳、各计数器值都要缓存。
- 采样间隔低于100ms意义不大——Linux
/proc/stat更新频率约10ms,但短于50ms波动剧烈;WindowsGetSystemTimes也受系统调度影响 - 所有时间差、计数差必须用
uint64_t,DWORD或long在64位系统上可能截断 - 别把两次采样放在不同线程里做——
std::chrono::steady_clock::now()虽线程安全,但计数器本身不是原子的,需保证读取顺序一致 - 如果用
std::this_thread::sleep_for等待,实际休眠可能比预期长(尤其在负载高时),应记录真实经过时间参与分母计算
别碰top、ps这类命令行工具的输出解析
用popen("top -bn1")或ps aux解析CPU字段看似简单,实则脆弱得离谱:
-
top默认按%CPU排序,输出格式随终端宽度、locale、版本变化(比如Ubuntu和CentOS的列顺序不同) -
ps的%cpu字段是进程级瞬时值,不是系统级,且采样逻辑与/proc/stat不一致 - 每次fork+exec开销大,频繁调用会拖慢你的程序,还可能被容器环境禁止
- 权限问题:某些受限容器里
/proc只挂载部分节点,但top可能根本跑不起来
真正难的不是读数据,而是理解“CPU占用率”本身没有唯一定义——它是对一段时间内非空闲周期的估算。采样窗口、计数粒度、是否包含iowait,都会让结果差5%~10%。与其追求“绝对准确”,不如统一采样策略、保持前后可比。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











