最可靠方式是直接读取/proc/meminfo中的memfree与memtotal计算比率,memfree代表严格空闲内存,非memavailable;windows须用globalmemorystatusex获取dwmemoryload反推空闲率。

Linux 下用 /proc/meminfo 计算空闲内存比率最可靠
直接读取 /proc/meminfo 是 Linux 上获取物理内存状态最轻量、最准确的方式。系统不提供“空闲比率”这种现成字段,但能通过 MemFree 和 MemTotal 自行计算——注意,MemFree 是真正未被使用的内存,不含 page cache 等可回收部分,所以它反映的是严格意义上的“空闲”,不是“可用”。
常见错误是把 MemAvailable 当作 MemFree 用:前者才是内核估算的“实际可分配内存”,包含可回收的 cache;若你真要监控“完全没被占用的内存”,必须用 MemFree。
- 打开
/proc/meminfo,逐行读取,匹配以MemFree:和MemTotal:开头的行 - 每行数值单位是 kB,需转为字节或统一用 kB 计算比率(避免整数溢出)
- 建议用
std::ifstream按行解析,不用system()或popen()——开销小、无 shell 依赖、不易被注入 - 示例片段:
long mem_free = 0, mem_total = 0;<br>std::ifstream f("/proc/meminfo");<br>std::string line;<br>while (std::getline(f, line)) {<br> if (line.rfind("MemFree:", 0) == 0) mem_free = std::stol(line.substr(8));<br> else if (line.rfind("MemTotal:", 0) == 0) mem_total = std::stol(line.substr(9));<br>}<br>double ratio = (mem_total > 0) ? static_cast<double>(mem_free) / mem_total : 0.0;</double>
Windows 下要用 GlobalMemoryStatusEx,别用已废弃的 GlobalMemoryStatus
GlobalMemoryStatus 只返回 32 位数值,在 4GB+ 内存机器上会溢出,导致 dwTotalPhys 和 dwAvailPhys 错误——这是很多老代码在 Win10/Win11 上算出负比率或 0% 的根本原因。
必须用 GlobalMemoryStatusEx,它填充 MEMORYSTATUSEX 结构体,所有字段都是 DWORDLONG(64 位),且 dwMemoryLoad 字段直接给出 0–100 的已用百分比,反推空闲率只需 100 - dwMemoryLoad,比自己除算更稳。
- 调用前必须设置
dwLength = sizeof(MEMORYSTATUSEX),否则 API 返回 false -
dwMemoryLoad是整数百分比(如 65 表示 65% 已用),不是浮点,精度够用 - 不需要管理员权限,普通进程可调用
- 示例关键行:
MEMORYSTATUSEX memInfo;<br>memInfo.dwLength = sizeof(MEMORYSTATUSEX);<br>if (GlobalMemoryStatusEx(&memInfo)) {<br> double idle_ratio = (100.0 - memInfo.dwMemoryLoad) / 100.0;<br>}
跨平台封装时,别硬写条件编译宏判断 OS,优先用 CMake 或构建系统隔离
在 .cpp 文件里堆 #ifdef _WIN32 / #elif __linux__ 容易让逻辑散乱、测试困难。更可控的做法是:把 Linux 和 Windows 的实现分别放在 mem_linux.cpp 和 mem_win.cpp,CMakeLists.txt 中按平台自动选源文件。
这样每个实现文件职责单一,单元测试也容易 mock——比如 Linux 版本可重定向 std::ifstream 读取伪造的 /proc/meminfo 内容,Windows 版本则用 stub 替换 GlobalMemoryStatusEx 函数指针。
- 不要在头文件里暴露平台相关类型(如
MEMORYSTATUSEX),用 wrapper struct 统一接口 - 返回值统一用
std::optional<double></double>,失败时返回std::nullopt,避免用 -1 或 NaN 作错误标记 - 如果项目已用 Conan 或 vcpkg,可考虑引入
fmt或spdlog做日志,但获取内存本身不该有 IO 或格式化开销
警惕“空闲”定义差异:监控用途和内存分配用途不能混用
运维监控看的是趋势,用 MemFree / MemTotal 没问题;但如果你是在写一个内存敏感的服务,想决定是否触发 GC 或降级策略,那应该看 MemAvailable(Linux)或 dwAvailPhys(Windows),因为它们反映的是“此刻能立刻分配出去的内存”。
尤其在容器环境里,/proc/meminfo 显示的是宿主机视图,而 cgroup 限制可能早已把可用内存压到很低——这时单看 MemFree 会严重误判。
- 容器中应优先读取
/sys/fs/cgroup/memory/memory.usage_in_bytes和memory.limit_in_bytes - Windows WSL2 用户注意:
/proc/meminfo返回的是 WSL2 虚拟机的内存,不是 Windows 宿主的 - 没有“通用安全阈值”:5% 空闲对桌面程序可能很宽裕,对实时音视频服务已是红色警报
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











