无法跨平台统一获取物理内存使用百分比,因windows、macos、linux数据来源与计算逻辑各异:windows用globalmemorystatusex基于ulltotalphys与ullavailphys计算;linux推荐/proc/meminfo中memavailable推算;macos需host_statistics64结合vm_statistics64_data_t各字段综合估算。

没有跨平台标准接口能直接拿到物理内存使用百分比,所有方案都得靠系统 API 封装,且 Windows/macOS/Linux 的数据来源和计算逻辑完全不同——硬写一个“统一函数”反而容易在某平台返回错误值。
Windows 下用 GlobalMemoryStatusEx 算百分比
Windows 提供的 MEMORYSTATUSEX 结构体里有 ullTotalPhys 和 ullAvailPhys,但注意:ullAvailPhys 是“当前可用物理内存”,不是“未被使用的物理内存”。它包含 standby list(待命页),这部分内存虽未被进程占用,但系统可能随时回收重用,所以严格来说不能直接用 (total - avail) / total 当作“已用率”。
更贴近用户感知的算法是:用 ullTotalPhys - ullAvailPhys 作为“已提交+活跃+待命外”的粗略已用值,再除以 ullTotalPhys。实际监控工具(如 Task Manager)也这么算。
实操建议:
- 必须调用
GlobalMemoryStatusEx,GlobalMemoryStatus已废弃且不支持 >4GB 内存 - 检查返回值是否为
TRUE,否则结构体字段未初始化 -
dwMemoryLoad字段是系统估算的整数百分比(0–100),可直接用,但它基于内核内部启发式逻辑,不一定和物理内存完全对应 - 示例片段:
MEMORYSTATUSEX mem; mem.dwLength = sizeof(mem); if (GlobalMemoryStatusEx(&mem)) { double percent = static_cast<double>(mem.ullTotalPhys - mem.ullAvailPhys) / mem.ullTotalPhys * 100.0; }</double>
Linux 下读 /proc/meminfo 并注意字段含义
Linux 没有“物理内存已用”单一指标,MemUsed 在较新内核(5.0+)才加入,旧版需自己算。关键字段是:
-
MemTotal:总物理内存(KB) -
MemFree:完全空闲页(不含 cache/buffer) -
Buffers:块设备缓存(page cache 的一部分) -
Cached:文件缓存(含 page cache + slabs) -
MemAvailable:内核估算的、可立即分配给新进程的内存(推荐用这个!)
推荐公式:(MemTotal - MemAvailable) / MemTotal * 100。它比 MemTotal - MemFree 更合理,因为 MemAvailable 已剔除不可快速回收的 slab 和部分 dirty page。
实操建议:
- 解析
/proc/meminfo时按行匹配,别依赖字段顺序 - 用
strtoull解析数值,跳过单位(如kB) - 若读不到
MemAvailable(老内核),退化到MemTotal - MemFree - Buffers - Cached,但结果偏高,慎用于告警阈值
macOS 用 host_statistics64 获取真实物理内存状态
macOS 不提供类似 /proc/meminfo 的文本接口,必须调用 Mach API。核心是 host_statistics64 + HOST_VM_INFO64,返回 vm_statistics64_data_t 结构体。
关键字段:
-
active_count:活跃页(最近被访问,很可能还在 RAM) -
inactive_count:非活跃页(可被换出,但内容干净) -
wire_count:锁定页(不能换出,如内核代码、驱动) -
free_count:空闲页 -
speculative_count:预读页(暂未使用,但已加载)
物理内存总量由 host_page_size * (active + inactive + wire + free + speculative) 得到;已用 ≈ active + inactive + wire(排除 speculative,因它不算真正“占用”)。
实操建议:
- 必须链接
-framework CoreServices -framework IOKit - 调用前要获取
mach_host_t(用mach_host_self()) - 注意
host_page_size不一定是 4096(虽然通常是),必须调用host_page_size获取 - 示例关键步骤:
vm_statistics64_data_t vm_stat; mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; kern_return_t kr = host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &count);
跨平台封装时最容易被忽略的是:Linux 的 MemAvailable 和 macOS 的 inactive_count 都含“可回收但未释放”的内存,而 Windows 的 ullAvailPhys 包含 standby list——三者语义接近但不等价。如果做统一监控面板,建议各平台单独实现、单独标注明细来源,别强行归一成一个数字。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











