Windows下用GlobalMemoryStatusEx获取可用物理内存需初始化MEMORYSTATUSEX的dwLength字段,调用后取ullAvailPhys字节数转MB;Linux读/proc/meminfo中MemAvailable字段(单位kB);macOS用host_statistics64结合free_count与vm_page_size计算,三者语义不同不可直接等价。

Windows 下用 GlobalMemoryStatusEx 获取可用物理内存
Windows 不暴露“可用物理内存”这个单一数值,而是通过 MEMORYSTATUSEX 结构体提供 ullAvailPhys 字段,它代表当前未被任何进程或系统内核锁定、可立即分配的物理内存字节数(含页面文件缓存中可快速回收的部分)。注意:这不是“空闲内存”,而是操作系统认为“此刻能拿来用”的总量。
实操要点:
立即学习“C++免费学习笔记(深入)”;
-
GlobalMemoryStatusEx必须传入已初始化的MEMORYSTATUSEX,且dwLength = sizeof(MEMORYSTATUSEX),否则返回false - 返回值为
bool,失败时调用GetLastError()查错,常见是结构体长度没设对 -
ullAvailPhys是ULONGLONG类型,直接除以 1024*1024 得到 MB,别用int接收,否则在 4GB+ 内存机器上溢出
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
if (GlobalMemoryStatusEx(&memInfo)) {
std::cout << "Available physical memory: " << memInfo.ullAvailPhys / (1024 * 1024) << " MB\n";
}Linux 下读取 /proc/meminfo 中的 MemAvailable
Linux 从 3.14 内核起引入 MemAvailable 行,它比旧的 MemFree 更准确——考虑了可回收的 slab、pagecache 中未锁页部分等。直接解析该行是最可靠方式,不建议自己算 MemFree + Buffers + Cached - Shmem,因为内核计算逻辑随版本变化。
实操要点:
立即学习“C++免费学习笔记(深入)”;
- 打开
/proc/meminfo后逐行读取,匹配以"MemAvailable:"开头的行(注意冒号和空格) - 数值单位是 kB,不是字节;需转换为字节时乘以 1024,转 MB 则除以 1024
- 某些嵌入式或精简发行版可能没有
MemAvailable(如老内核或禁用该特性),此时 fallback 到MemFree并加注释说明精度下降
std::ifstream f("/proc/meminfo");
std::string line;
while (std::getline(f, line)) {
if (line.substr(0, 13) == "MemAvailable:") {
size_t pos = line.find_first_of("0123456789");
if (pos != std::string::npos) {
long kb = std::stol(line.substr(pos));
std::cout << "Available physical memory: " << kb / 1024 << " MB\n";
}
break;
}
}macOS 使用 host_statistics64 和 HOST_VM_INFO64
macOS 没有类似 /proc/meminfo 的接口,必须通过 Mach API 调用 host_statistics64 获取 vm_statistics64_data_t,其中 free_count 是空闲页数,乘以 vm_page_size 才是字节数。但注意:这仅是真正空闲页,不含可回收缓存,结果通常显著低于 Linux 的 MemAvailable 或 Windows 的 ullAvailPhys。
实操要点:
立即学习“C++免费学习笔记(深入)”;
- 需要链接
-framework CoreServices和-framework IOKit,编译时别漏 -
host_statistics64返回的是kern_return_t,成功值为KERN_SUCCESS,不是 0 或 true -
vm_page_size必须用host_page_size查询,不能硬编码 4096 —— macOS 支持大页,实际页大小可能不同
vm_statistics64_data_t vm_stat;
mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
kern_return_t ret = host_statistics64(mach_host_self(), HOST_VM_INFO64,
(host_info64_t)&vm_stat, &count);
if (ret == KERN_SUCCESS) {
vm_size_t page_size;
host_page_size(mach_host_self(), &page_size);
uint64_t avail_bytes = (uint64_t)vm_stat.free_count * page_size;
std::cout << "Available physical memory: " << avail_bytes / (1024 * 1024) << " MB\n";
}跨平台封装时最易忽略的兼容性细节
不同系统对“可用物理内存”的定义差异很大:Windows 包含可快速释放的缓存页,Linux 的 MemAvailable 做了更精细的估算,macOS 只报真正空闲页。这意味着同一台机器,三个平台返回的数值可能相差 2–3 倍。
如果你在写跨平台监控工具或资源调度逻辑,不要直接比较绝对值,更别拿它做内存不足告警阈值。实际使用中:
- 优先用各平台原生推荐方式(即上面三段列出的),别试图统一成一个公式
- macOS 上若需接近 Linux 的语义,得额外估算 inactive + speculative 页,但稳定性差,一般不建议
- 所有路径读取、API 调用都应加错误 fallback,比如 Linux 读
/proc/meminfo失败时返回 -1,Windows 调用失败时查GetLastError()是否为ERROR_INVALID_PARAMETER
数值本身容易拿到,但“可用”二字背后是各系统内核的策略差异,这点不厘清,后续逻辑很容易误判。


















