Linux通过/proc/stat首行cpu字段获取CPU总jiffies(user+nice+system+idle+iowait+irq+softirq+steal之和)与空闲时间(idle+iowait),Windows需调用GetSystemTimes并提权,总时间=内核+用户−空闲,空闲比例=空闲/总时间。

Linux下用/proc/stat读取CPU总运行时间与空闲时间
Linux内核通过/proc/stat暴露各CPU核心的累计运行时间(单位:jiffies),第一行cpu是所有核心的汇总。关键字段顺序固定:cpu user nice system idle iowait irq softirq steal guest guest_nice。其中user+nice+system+idle+iowait+irq+softirq+steal之和即为总jiffies;idle+iowait可近似作为空闲时间(严格说iowait是等待I/O的可调度状态,但多数监控场景将其计入空闲)。
实操建议:
- 用
std::ifstream打开/proc/stat,逐行读取,匹配以"cpu "开头的首行(注意末尾空格,避免匹配到cpu0等) - 用
std::istringstream解析后续整数,跳过第一个字符串,按序提取前8个数值(C++11起支持std::stoull防溢出) - 两次采样间隔建议≥100ms,否则
idle变化可能为0,导致除零或比例失真 - 不要直接用
system字段计算负载——它不含irq/softirq,会低估内核态开销
Windows下用GetSystemTimes获取CPU时间
Windows不提供类似/proc/stat的文本接口,必须调用WinAPI:GetSystemTimes返回三个FILETIME结构,分别表示空闲时间、内核时间(含空闲)、用户时间。总运行时间 = 内核时间 + 用户时间 - 空闲时间;空闲比例 = 空闲时间 / 总时间(注意单位是100ns,需转为相同量纲)。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 未启用
SE_INCREASE_QUOTA_NAME特权时,GetSystemTimes返回FALSE且GetLastError()为ERROR_ACCESS_DENIED - 直接比较
FILETIME结构体(而非其QuadPart)导致大小判断失效 - 未将
FILETIME转为64位整数就做减法,高位截断引发负值
正确做法:
- 调用
OpenProcessToken+LookupPrivilegeValue+AdjustTokenPrivileges提权(仅首次需要) - 用
ULARGE_INTEGER或static_cast<uint64_t>(ft.dwHighDateTime) 转换时间</uint64_t> - 空闲时间可能大于内核时间(因内核时间含空闲),所以总时间必须用
kernelTime + userTime - idleTime,而非kernelTime + userTime
C++跨平台封装时的陷阱:jiffies与100ns单位不可混用
Linux的jiffies依赖HZ配置(通常250或1000),而Windows固定为100ns。若封装统一接口返回“毫秒级CPU时间”,必须在各自平台做单位归一化,否则两次采样差值会数量级错乱。
性能与兼容性影响:
- Linux下反复读
/proc/stat开销极低(内核内存映射,无磁盘IO),但频繁调用(如每1ms)仍会增加系统调用次数 - Windows下
GetSystemTimes是轻量调用,但提权操作应只执行一次,避免重复AdjustTokenPrivileges - macOS不支持这两者,需改用
host_processor_info(mach API),字段含义和更新频率与Linux/Windows均不同,无法简单复用同一套解析逻辑
计算空闲比例时为何不能只看idle字段
现代CPU有多种低功耗状态(C-states),idle仅统计内核调度器进入空闲循环的时间,不包含硬件自主降频、深度睡眠等由固件管理的时间。监控工具常把iowait(Linux)或Idle以外的待机时间(Windows性能计数器中的% Idle Time)纳入空闲,是因为用户真正关心的是“此刻能否立即响应任务”。
所以实际工程中:
- Linux推荐用
idle + iowait作为分子,分母为全部非guest时间(即排除虚拟机占用) - Windows直接采用
GetSystemTimes返回的lpIdleTime,它已由内核聚合了硬件空闲时间 - 避免用
top或htop显示的“%Cpu(s): xx us, yy sy, zz id”反推——它们对iowait的处理策略不透明,且采样周期不可控
最易被忽略的是:两次采样间若有CPU频率动态调整(如Intel SpeedStep),jiffies计数不变但真实耗时变化,此时比例反映的是“指令执行占比”而非“物理时间占比”。需要更高精度时,得结合RDTSC或clock_gettime(CLOCK_MONOTONIC)对齐时间基准。


















