linux下计算总cpu负载率需解析/proc/stat的cpu行,取两次采样差值:总时间=所有时间字段和,负载率=(总时间−idle−iowait)/总时间,推荐间隔500ms采样并用std::ifstream安全读取。

Linux 下读取 /proc/stat 计算总 CPU 负载率
Linux 没有“系统级实时 CPU 负载率”的现成 API,必须自己解析 /proc/stat。该文件第一行(cpu 行)包含所有 CPU 的累加时间,字段顺序固定:cpu user nice system idle iowait irq softirq steal guest guest_nice。关键不是看单次值,而是两次采样差值。
- 至少间隔 100ms 以上采样,否则差值可能为 0 或失真
-
user和nice合并为用户态时间;system、irq、softirq合并为内核态时间;idle和iowait都算空闲(但严格说iowait是可运行但等 I/O 的状态,多数监控工具将其计入 idle) - 总时间 =
user + nice + system + idle + iowait + irq + softirq + steal;负载率 =(total - idle) / total
C++ 实现采样与计算的最小可靠代码
用 std::ifstream 读 /proc/stat 比 FILE* 更易控制,但要注意:不能只读一行就停,必须跳过以 cpu 开头的首行;字段数可能因内核版本略有差异(如较新内核多出 guest_nice),建议按位置而非字段名提取。
#include <fstream>
#include <vector>
#include <chrono>
#include <iostream><p>std::vector<long long> read_cpu_times() {
std::ifstream f("/proc/stat");
std::string line;
while (std::getline(f, line)) {
if (line.substr(0, 3) == "cpu ") { // 注意末尾空格,排除 cpu0 等
std::istringstream iss(line);
std::string cpu;
iss >> cpu;
std::vector<long long> times;
long long t;
while (iss >> t) times.push_back(t);
return times; // 至少 8 个值,多余忽略
}
}
return {};
}</long></long></p></iostream></chrono></vector></fstream>
调用时需两次采样,中间用 std::this_thread::sleep_for(std::chrono::milliseconds(500)) 控制间隔;避免用 clock_gettime 或 gettimeofday 做精确计时——这里只需要稳定间隔,非微秒级同步。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
区分用户态和内核态负载的常见误判点
很多人把 system 时间直接当“内核态负载”,但实际还有 irq 和 softirq ——它们也是内核执行的上下文,比如网卡中断、定时器软中断。若只算 system,会低估真实内核开销,尤其在高吞吐网络服务中偏差可达 10%~20%。
- 用户态负载 =
(user + nice)/ 总时间 - 内核态负载 =
(system + irq + softirq)/ 总时间 -
steal时间表示虚拟机被宿主机偷走的 CPU,应单独统计,不计入用户/内核负载 - 注意:
idle不等于“CPU 没事干”,它包含调度器无任务可选的周期,而iowait是进程在等待磁盘/网络完成时的主动让出,两者语义不同,但多数场景下合并进 idle 更符合传统负载定义
跨平台兼容性问题:Windows 上没法直接套用
Windows 没有 /proc/stat,得用 PDH(Performance Data Helper)API 查询 \Processor(_Total)\% Processor Time 计数器。但它只返回总占用率,不拆分用户/内核态——因为 Windows 内部没有完全对应的运行态划分(例如 DPC、中断处理时间不暴露给用户态监控)。
- 若必须跨平台,建议 Linux 用
/proc/stat,Windows 用PdhCollectQueryData+PdhGetFormattedCounterValue,但接受用户/内核态不可分的事实 - macOS 类似 Windows,需用
host_processor_info,返回的cpu_ticks数组含USER_STATE、SYSTEM_STATE、IDLE_STATE,但SYSTEM_STATE包含中断和内核线程,无法再细分 - 不要尝试用
getrusage或clock_gettime(CLOCK_PROCESS_CPUTIME_ID)——那是单进程 CPU 时间,不是系统级
真正难的不是读数据,而是理解每个字段在不同内核版本下的语义漂移,比如 5.14+ 新增的 guest_nice 字段会让老代码越界访问;还有容器环境下 cgroup 的 CPU throttling 会导致 steal 异常升高,但并不反映物理 CPU 真实负载。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










