最可靠的方式是直接读取 /proc/meminfo 中的 memavailable 字段(内核 3.14+),用 std::ifstream 解析其值(单位 kb)并转为 mb;若不存在则降级使用 memfree + buffers + cached,但需注意准确性下降。

直接读取 /proc/meminfo 是最可靠的方式
Linux 内核通过 /proc/meminfo 向用户空间暴露内存统计,其中 MemAvailable 字段(内核 3.14+)才是你真正该用的“可用内存”指标,它比 MemFree 更准确,已扣除不可回收的 slab、page cache 等。C++ 没有标准库函数能跨平台获取这个值,硬编码调用系统命令(如 free)反而容易出错或受 locale 影响。
实操建议:
- 用
std::ifstream打开/proc/meminfo,逐行读取并查找以MemAvailable:开头的行 - 跳过前导空格后,提取第一个整数(单位是 kB),除以 1024 得到 MB
- 如果内核太老(
MemAvailable不存在),降级 fallback 到MemFree+Buffers+Cached(但注意:Cached在较新内核中含不可回收部分,不推荐手动拼凑) - 务必检查
std::stoi是否抛异常,或用std::strtol做更安全的转换
sysinfo() 返回的是近似值,且单位易混淆
sysinfo() 系统调用确实能拿到 freeram 字段,但它返回的是“空闲页帧数”,单位是 sysconf(_SC_PAGESIZE),不是字节也不是 kB。很多教程直接乘以 4096 是错的——页面大小在不同架构下可能不同(ARM64 可能是 64KB)。而且 freeram 不包含可回收的 page cache,数值通常比 /proc/meminfo 中的 MemAvailable 小得多。
实操建议:
- 调用前必须先
#include <sys></sys>和<unistd.h></unistd.h> - 用
sysconf(_SC_PAGESIZE)获取真实页面大小,别硬写 4096 -
struct sysinfo的totalsram和freeram都是 unsigned long,溢出风险低,但需注意 32 位系统上 long 可能只有 4 字节 - 返回值为 0 表示成功,-1 表示失败(比如权限不足),必须检查
避免用 get_phys_pages() 和 get_avphys_pages()
这两个函数常被误认为是“获取总物理内存”和“获取可用物理内存”的捷径,但它们返回的是页数(不是字节数),而且 get_avphys_pages() 实际调用的是 sysinfo() 的 freeram,和上面说的一样——它不等于 MemAvailable。更麻烦的是,它们定义在 <unistd.h></unistd.h>,但 GNU libc 文档明确标注“not portable”,某些嵌入式 libc(如 musl)根本不提供。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
实操建议:
- 除非你明确只要“当前不可分配的空闲页帧数”,否则不要用
get_avphys_pages() - 不要对返回值直接除以 1024 当作 MB——它单位是页,不是 kB
- 若编译时报错
undefined reference to `get_avphys_pages',说明你的 libc 不支持,别硬加链接选项
示例代码只做关键路径,不封装成通用函数
实际项目里,你大概率只需要一次读取,没必要抽象成类或单例。下面这段代码能跑通、有错误处理、单位正确,且不依赖外部命令:
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
int get_mem_available_mb() {
std::ifstream f("/proc/meminfo");
std::string line;
while (std::getline(f, line)) {
if (line.rfind("MemAvailable:", 0) == 0) {
std::istringstream iss(line.substr(13));
long kb = 0;
iss >> kb;
return static_cast<int>(kb / 1024);
}
}
return -1; // not found
}
</int></iostream></sstream></string></fstream>
注意 line.substr(13) 是因为 "MemAvailable: " 长度为 13(含冒号和空格);如果某发行版在字段后加了单位(如 kB),std::istringstream 会自动停在非数字字符处,不影响结果。
真正容易被忽略的点:/proc 是虚拟文件系统,读取本身很快,但如果你在高频率监控场景(比如每秒多次)里反复打开关闭 /proc/meminfo,fd 创建销毁开销会比预期大;这时才值得考虑 mmap 或缓存解析结果——但绝大多数应用根本不需要。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










