windows上获取物理内存使用率应使用globalmemorystatusex,因其跨版本、无需管理员权限且可靠;它返回绝对数值,需自行计算百分比,而getperformanceinfo和wmi不适用或存在性能/稳定性问题。

Windows 上没有直接返回“物理内存使用率百分比”的系统 API,GlobalMemoryStatusEx 是唯一可靠、跨版本(XP SP2+)、无需管理员权限的方案,它返回的是绝对数值,百分比必须自己算。
为什么不能用 GetPerformanceInfo 或 WMI?
GetPerformanceInfo 虽然也提供内存信息,但它返回的 CommitLimit 和 CommitTotal 是页面文件相关的提交限制/用量,不是物理内存;WMI(如 Win32_OperatingSystem)底层仍调用 GlobalMemoryStatusEx,但多一层 COM 开销、启动慢、可能被禁用或超时——对进程监控这种低延迟场景不适用。
常见错误现象:GetPerformanceInfo 返回的 PhysicalPagesUsed 常为 0 或明显偏小;WMI 查询在容器或精简系统中直接失败,抛出 WBEM_E_ACCESS_DENIED 或超时。
- 仅需读取物理内存总量和可用量 → 用
GlobalMemoryStatusEx - 需要每秒多次采样(如监控面板)→ 避免 WMI 或性能计数器
- 目标系统含 Windows Server Core / Nano / Docker Desktop 内嵌 WinNT →
GlobalMemoryStatusEx是唯一稳定选择
GlobalMemoryStatusEx 的正确用法和关键字段
必须初始化 MEMORYSTATUSEX::dwLength,否则函数返回 FALSE 且不填充数据;实际可用内存是 ullAvailPhys,不是 ullAvailPageFile 或 ullAvailVirtual。
MEMORYSTATUSEX mem;
mem.dwLength = sizeof(mem);
if (GlobalMemoryStatusEx(&mem)) {
double percent = 100.0 * (mem.ullTotalPhys - mem.ullAvailPhys) / static_cast<double>(mem.ullTotalPhys);
// 注意:mem.ullTotalPhys 可能为 0(极罕见硬件异常),需防护
}</double>
参数差异:
-
ullTotalPhys:真实物理内存字节数(BIOS 报告值,不含预留硬件区域) -
ullAvailPhys:当前可被用户模式进程立即使用的物理内存字节数(已剔除内核占用、驱动锁定、硬件保留页) - 不要用
ullAvailPageFile计算——它包含页面文件空间,与“物理内存使用率”概念无关
精度、线程安全与采样频率注意事项
该 API 是轻量级内核态查询,无锁、无分配、无同步开销,可在任意线程高频调用(实测 10kHz 调用无压力);但 Windows 内存统计本身有约 100–500ms 滞后(内核定期更新 MmAvailablePages),所以连续两次 10ms 间隔调用结果几乎总是一样的。
容易踩的坑:
- 未检查
GlobalMemoryStatusEx返回值,直接使用未初始化的mem结构 → 读到垃圾值,百分比爆成负数或 >100% - 用
int或unsigned long接收ullTotalPhys→ 在 4GB+ 内存机器上整数溢出,结果归零 - 在 DLL 的
DLL_PROCESS_ATTACH中首次调用 → 极少数旧版系统(如 WinXP SP1)可能触发延迟加载失败(已基本绝迹,但仍建议加 try/catch 包裹)
真正影响准确性的不是 API 本身,而是“物理内存使用率”这个指标本身的语义模糊:Windows 会把大量空闲内存用于 Standby List 缓存,这部分内存既不算“已用”,也不算“可用”(ullAvailPhys 不含它),但一旦应用申请就会立刻回收。所以你看到的百分比,永远比任务管理器显示的“内存使用率”略低——这是设计使然,不是 bug。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











