无法跨平台直接获取物理内存使用百分比,需按系统调用API:Windows用GlobalMemoryStatusEx但需注意ullAvailPhys不含可回收缓存,Linux应使用MemAvailable而非MemFree计算。

没有跨平台的 C++ 标准接口能直接获取物理内存使用百分比;必须按操作系统分别调用系统 API,且“使用率”的定义本身在不同平台不一致。
Windows 下用 GlobalMemoryStatusEx 算百分比
Windows 提供的 MEMORYSTATUSEX 结构体包含 ullTotalPhys 和 ullAvailPhys,但注意:ullAvailPhys 是“当前可用物理内存”,不是“未被使用的物理内存”——它不含被系统缓存(如 Standby List)占用但可立即回收的部分。所以直接用 (Total - Avail) / Total 会高估使用率,和任务管理器显示不一致。
- 任务管理器实际参考的是
PERF_MEMORY_COMMIT_LIMIT和PERF_MEMORY_COMMIT_BYTES(即提交内存),但该数据需通过PdhAddCounter查询性能计数器,开销大、延迟高 - 更实用的做法是:用
GlobalMemoryStatusEx+ 人工排除 Page File 缓存影响,或接受与任务管理器约 ±3% 的偏差 - 示例关键片段:
MEMORYSTATUSEX mem{}; mem.dwLength = sizeof(mem); GlobalMemoryStatusEx(&mem); double pct = 100.0 * (mem.ullTotalPhys - mem.ullAvailPhys) / mem.ullTotalPhys;
Linux 下读 /proc/meminfo 并理解字段含义
Linux 没有单一“物理内存使用量”,MemAvailable(内核 3.14+)才是最接近 Windows “可用内存”的指标,而 MemFree 仅表示完全空闲页,严重低估可用性。错误地用 (MemTotal - MemFree) / MemTotal 会导致 70%+ 的虚假高负载。
- 推荐公式:
(MemTotal - MemAvailable) / MemTotal * 100.0,它已隐含了 page cache、slab 等可回收内存的估算 - 若内核太老(MemAvailable 不存在,退化为
MemTotal - MemFree - Buffers - Cached(仍比只减MemFree准确) - 解析时注意单位统一为 kB,且跳过带
#的注释行;字段后可能有冒号和空格,建议用std::string::find(':')定位值起始位置
macOS 需组合 host_statistics64 和 vm_statistics64
macOS 不暴露简单总/可用值,必须调用 Mach API 获取 vm_statistics64_data_t,再手动计算“活跃 + 非活跃 + wired”作为近似已用内存。但 pages_wired(被内核锁定的内存)不能释放,pages_inactive 可随时回收——所以直接加总仍会高估压力。
- 关键步骤:先用
host_port = mach_host_self(),再host_statistics64(host_port, HOST_VM_INFO64, ...) - 计算式建议:
(stat.pages_active + stat.pages_inactive + stat.pages_wired) * page_size / total_bytes * 100.0,其中page_size = vm_page_size - 注意:macOS 的
pages_free包含压缩内存(purgeable),单独看意义不大;且vm_statistics64在某些 macOS 版本需 root 权限才能读取完整字段
封装跨平台接口时最容易忽略的三个点
写一个 get_physical_memory_usage_percent() 函数看似简单,但以下三点常导致线上监控误报:
- Windows 下未检查
GlobalMemoryStatusEx返回值,失败时返回垃圾值(应返回 -1 或抛异常) - Linux 解析
/proc/meminfo时没处理字段缺失(如旧内核无MemAvailable),直接std::stoull崩溃 - macOS 中
vm_page_size是运行时变量,不能硬编码为 4096——M1/M2 芯片支持 16KB 大页,host_page_size才是安全选择
真实环境里,内存使用率的“合理性”比“绝对精度”更重要;与其追求和系统监视器像素级一致,不如确保多平台间趋势一致、突变可归因、且不会因字段缺失或权限不足而静默失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











