<p>最可靠方式是两次读取/proc/stat中cpu行计算差值:1.0 - (idle_delta + iowait_delta + steal_delta) / total_delta,间隔≥200ms,用unsigned long long解析,逐行匹配cpu\d+获取各核数据。</p>

Linux 下用 /proc/stat 计算全局 CPU 使用率最可靠
直接读 /proc/stat 是 Linux 获取总 CPU 负载的底层方式,比调用第三方库更轻量、无依赖,且天然支持多核聚合。第一行 cpu(不带数字后缀)给出的是所有 CPU 核心的累计时间片总和。
关键点:需采集两次快照,间隔至少 100ms,否则差值为 0 或失真。计算公式是 (idle_time_delta) / (total_time_delta) 的补集,即 1.0 - idle_delta / total_delta。
- 每次读取要跳过前 5 个字段(
cpu、user、nice、system、idle),第 5 项是idle,第 6 项是iowait,都算空闲时间;严格来说应把idle+iowait+steal(如果存在)作为总空闲时间 - 注意
/proc/stat中数值是 unsigned long long,C++ 里必须用unsigned long long读,用%llu格式化,否则在高负载长时间运行的机器上会溢出回绕 - 不要只采一次——单次读取只能得瞬时快照,无法区分是短时抖动还是持续负载;最小建议间隔 200ms,太短误差大,太长响应滞后
获取每核明细必须解析 cpu0、cpu1 等独立行
/proc/stat 后续每一行以 cpuN 开头的就是对应逻辑核的统计,N 从 0 开始。总数取决于 sysconf(_SC_NPROCESSORS_ONLN),但别硬编码循环到固定数——有些系统(如容器)可能隐藏部分核,应逐行读取并匹配 ^cpu[0-9]+ 行。
每核计算逻辑和全局一致,但要注意:各核的 idle 时间不具可加性,不能简单把所有核 idle 加起来除以总核数;必须对每核单独算使用率再平均,或按权重(如频率)加权。
立即学习“C++免费学习笔记(深入)”;
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 用
std::regex提取cpu\d+行较重,推荐用std::string::find判断行首是否为"cpu"再检查第三个字符是否为数字 - 某些 ARM 或虚拟化环境会出现
cpu000这类带前导零的名称,正则要写成^cpu[0-9]+而非^cpu[0-9] - 如果某核长时间 idle(比如节能状态),其
idle值可能停滞不动,此时 delta 为 0,计算出的使用率为 0% —— 这是正常行为,不是 bug
Windows 上必须用 PdhCollectQueryData + PdhGetFormattedCounterValue
Windows 没有类似 /proc/stat 的文本接口,WMI 太慢,GetSystemTimes 只返回内核/用户时间,缺 idle 时间。唯一稳定方案是 Performance Data Helper(PDH)API,目标计数器是 \Processor(_Total)\% Processor Time(全局)和 \Processor(0)\% Processor Time(单核)。
PDH 初始化开销大,但可复用查询句柄;每秒调用一次 PdhCollectQueryData 即可,无需手动差值计算——Windows 已内部处理好百分比。
- 首次调用
PdhCollectQueryData返回PDH_INVALID_DATA是正常现象,必须调用两次以上才能拿到有效值 - 计数器路径中的
_Total和0等索引是字符串字面量,不是整数变量;枚举逻辑核要用PdhEnumObjectItems查"Processor"对象的实例名,不能假设从 0 到 N-1 连续 - 某些精简版 Windows 或组策略禁用性能计数器时,
PdhAddCounter会失败,需 fallback 到GetTickCount64+GetProcessTimes估算当前进程占比,但无法反映系统级总负载
跨平台封装时别碰 std::thread::hardware_concurrency()
这个函数返回的是“硬件支持的最大并发线程数”,不是当前可用逻辑核数,更不是 CPU 总数。它在容器、WSL、虚拟机中常返回宿主机值,且不随热插拔变化,在 macOS 上甚至可能返回 0。真正需要核数的地方,Linux 用 sysconf(_SC_NPROCESSORS_ONLN),Windows 用 GetActiveProcessorCount(Win10+)或 GetSystemInfo.dwNumberOfProcessors(兼容旧版)。
更隐蔽的坑是:即使你正确获取了核数,/proc/stat 中的 cpuN 行数量也可能少于该值——内核可能因节能关闭部分核心,导致其统计行消失。所以始终以实际读到的 cpuN 行为准,而不是预分配数组。
最后提醒:CPU 负载率本质是时间占比,不是队列长度或等待线程数;它无法反映 I/O 瓶颈或内存带宽饱和。如果看到负载 80% 但响应迟钝,大概率问题不在 CPU。

















