Linux用/proc/[pid]/stat和/proc/stat差值法算CPU使用率,需取utime/stime与系统总时间,间隔≥100ms采样;Windows用GetProcessTimes与GetSystemTimeAsFileTime差值比,单位均为100纳秒,建议间隔≥500ms。

Linux下用/proc/[pid]/stat和/proc/stat算CPU使用率
Linux没有系统调用直接返回进程CPU使用率,得靠解析/proc伪文件系统。核心思路是:读取当前进程的/proc/self/stat拿到累计的utime(用户态时间)和stime(内核态时间),再读/proc/stat获取系统总CPU时间,两次采样做差值后归一化。
注意几个坑:
-
/proc/self/stat第14、15字段是utime和stime(单位是CLK_TCK,通常是100),不是毫秒或秒 -
/proc/stat第一行cpu后面那几列才是总时间,要跳过cpu字符串再解析 - 必须间隔至少100ms以上采样,否则差值为0导致除零或结果失真
- 单次计算只能反映“区间平均”,不是瞬时值;想接近实时就得高频采样+滑动窗口
Windows下用GetProcessTimes配合GetSystemTimeAsFileTime
Windows没现成的百分比接口,但能拿到进程的总用户/内核时间(GetProcessTimes)和系统启动以来的总时间(GetSystemTimeAsFileTime)。关键在于:进程时间是累加值,而系统时间代表“流逝的墙钟时间”,两者单位都是100纳秒,所以CPU使用率 ≈ (进程总CPU时间 / 系统总运行时间) × 100%。
实操要点:
- 调用
GetProcessTimes前必须用GetCurrentProcess()获取当前进程句柄 -
GetSystemTimeAsFileTime返回的是自1601年1月1日以来的100纳秒数,要减去系统启动时间才对应“系统已运行多久”——但这个启动时间得从GetTickCount64反推,更简单的方法是两次调用GetSystemTimeAsFileTime取差值作为时间跨度 - 如果只算单次,结果会严重偏低(因为进程启动后可能大部分时间在休眠),建议至少间隔500ms以上再算一次差值
跨平台封装要注意的陷阱
别指望std::this_thread::get_id()或std::chrono能直接给出CPU占用——它们跟操作系统调度器完全无关。真要跨平台,得条件编译:
- Linux走
/proc路径,注意utime+stime只是该进程的,不包含子进程(除非开task/[tid]/stat遍历线程) - Windows下
GetProcessTimes默认包含子进程时间(取决于创建时是否设CREATE_NO_WINDOW等标志),如需精确到本进程,得用PROCESS_QUERY_LIMITED_INFORMATION权限并确认子进程已分离 - 所有时间值都是
FILETIME或clock_t类型,直接相减可能溢出,务必转成uint64_t再算 - 权限问题:Linux下
/proc/[pid]对其他用户进程可能不可读;Windows上若以低完整性级别运行,GetProcessTimes可能失败返回ERROR_ACCESS_DENIED
为什么top或ps显示的值你很难复现
终端工具如top其实做了大量平滑处理:它们维护一个历史时间窗口(比如过去20次采样),用加权平均抑制抖动;还动态调整采样频率(负载高时降频,避免自身吃太多CPU);更关键的是,它们把“CPU时间 / (采样间隔 × CPU核心数)”作为分母——你如果忽略核心数,算出来永远偏高。
实际写代码时最容易漏掉这点:假设双核机器上进程用了100ms CPU时间,间隔1s采样,你以为是10%,其实是20%(因为1s内两颗核最多提供2000ms总时间)。不除以sysconf(_SC_NPROCESSORS_ONLN),结果就废了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











