直接读取 /proc/loadavg 文件最可靠,因其无需特权、无依赖、无精度误差;前三列即1/5/15分钟load average,应使用 std::istringstream 安全解析,避免 std::stof() 或 getloadavg() 的兼容性与异常风险。

直接读取 /proc/loadavg 文件最可靠
Linux 内核通过 /proc/loadavg 暴露系统 1/5/15 分钟 Load Average,这是唯一无需特权、无依赖、不引入额外精度误差的方式。C++ 程序只需以文本方式打开并解析该文件,比调用 getloadavg() 更稳定(后者在某些 musl 或旧 glibc 上可能返回 -1)。
常见错误是尝试用 sysinfo() 或 getloadavg() 并忽略返回值检查 —— 它们失败时不抛异常,只静默返回负值或截断结果。
-
/proc/loadavg前三列即为 1/5/15 分钟均值,格式固定为"1.23 0.98 0.76 2/892 12345" - 必须用空格分隔,不能用
std::stof()直接扫整行 —— 第四列含斜杠,第五列为进程数,会触发转换异常 - 建议用
std::istringstream配合skipws逐字段提取,或用strtof()手动定位空格后偏移
getloadavg() 的兼容性陷阱
POSIX 标准函数 getloadavg() 看似简洁,但在实际部署中容易出问题:musl libc(Alpine 默认)不实现它;某些嵌入式 glibc 裁剪版也禁用;即使可用,传入长度小于 3 时行为未定义,且返回值是 double 数组而非引用参数,易误写成 getloadavg(&a, 1) 导致越界读。
使用前必须检查返回值:if (getloadavg(load, 3) != 3),否则可能拿到未初始化的栈内存值。
- 头文件需包含
<unistd.h></unistd.h>,不是<sys></sys> - 数组长度必须 ≥3,否则函数可能不填充全部三个值
- 返回值为成功写入的元素个数,非负数不等于“成功”,必须严格比对
解析示例:安全读取前三值
下面这段代码绕过所有常见坑,适用于 glibc/musl/Android NDK:
#include <fstream>
#include <sstream>
#include <string><p>bool read_loadavg(float& one, float& five, float& fifteen) {
std::ifstream f("/proc/loadavg");
if (!f.is_open()) return false;
std::string line;
if (!std::getline(f, line)) return false;
std::istringstream iss(line);
return (iss >> one >> five >> fifteen);
}</p></string></sstream></fstream>
注意:不用 std::stof() 是因为 std::istringstream 在字段缺失时设 failbit,可统一判断;而 stof() 遇非法字符会抛 std::invalid_argument 或静默截断。
为什么不用 sysinfo()?
sysinfo() 返回的 loads[3] 字段是左移 8 位的定点数(如 1.23 存为 1.23 * 256 ≈ 315),需手动除以 1(通常是 256)。但该宏在部分头文件中未暴露,且 <code>SI_LOAD_SHIFT 值依赖内核配置,用户空间不可靠。
更关键的是:sysinfo() 可能因权限被 seccomp 过滤,或在容器中被 cgroup 限制而返回 -1,而 /proc/loadavg 是纯虚拟文件,只要 procfs 挂载就一定可读。
复杂点在于:Load Average 是调度器统计的“就绪态 + 不可中断态”进程数的指数加权移动平均,数值本身受 CPU 数量、I/O 延迟模型影响,同一数值在不同机器上含义并不等价 —— 但获取方式本身,/proc/loadavg 就是事实标准。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











