在系统编程中,获取物理内存总量是一个看似简单,实则暗藏不少细节的任务。不同平台下的API调用方式各异,稍有不慎,拿到的数据就可能与预期相差甚远。先说几个关键点:Linux下应当读取/proc/meminfo并解析MemTotal字段,而Windows下则需要正确初始化MEMORYSTATUSEX.dwLength后再调用GlobalMemoryStatusEx。这两个接口返回的是内核可用的物理内存,而非BIOS安装容量或sysconf的估算值。

C++如何获取系统的物理内存总量 _ sysconf与GlobalMemoryStatusEx【实战】

Linux下用sysconf算不准?

你可能会发现,直接拿sysconf(_SC_PHYS_PAGES)sysconf(_SC_PAGESIZE)相乘,得到的结果往往比/proc/meminfo里的MemTotal小那么几十MB。这不是精度问题,而是_SC_PHYS_PAGES返回的其实是内核**可管理的物理页数**,并不包括被固件、预留内存(比如iommu、CMA、GPU显存)占用的那部分。

所以,正确的做法就清晰了:读取/proc/meminfo并解析MemTotal:那一行。

#include 
#include 
#include 

long long get_physical_memory_linux() {
    std::ifstream f("/proc/meminfo");
    std::string line;
    while (std::getline(f, line)) {
        if (line.rfind("MemTotal:", 0) == 0) {
            std::istringstream iss(line.substr(9));
            long long kb;
            iss >> kb;
            return kb * 1024LL; // 转为字节
        }
    }
    return -1;
}

这里有几个细节值得注意:

Windows下GlobalMemoryStatusEx返回0?

这个问题的症结,十有八九是没初始化MEMORYSTATUSEX结构体的dwLength字段。这个API的规矩是“先填长度再调用”,不设就直接失败,而且不报错,ullTotalPhys自然就保持未初始化值,常为0。

正确的写法如下:

#include 

uint64_t get_physical_memory_windows() {
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(memInfo); // 必须!否则ullTotalPhys无效
    if (GlobalMemoryStatusEx(&memInfo)) {
        return memInfo.ullTotalPhys;
    }
    return 0;
}

这里同样有几个要点:

跨平台封装时,用命令行调freewmic靠不靠谱?

不推荐。命令行方式有三类硬伤:启动开销大、输出格式不稳定(locale会影响单位、空格、换行)、权限受限(比如WSL2里wmic不可用,容器中free可能缺失)。

为什么GetPhysicallyInstalledSystemMemoryGlobalMemoryStatusEx还少?

GetPhysicallyInstalledSystemMemory读取的是BIOS/UEFI DMI表里的物理插槽容量总和,而GlobalMemoryStatusEx::ullTotalPhys是内核实际映射并可用的物理内存。两者之间的差值,就是被硬件保留、无法被OS使用的部分(比如集成显卡固定占用的512MB)。

实际项目里最容易被忽略的点,就是没有区分“物理安装容量”“内核可用物理内存”“用户态可用虚拟内存”这三个概念。它们在服务器、游戏、嵌入式场景下的意义完全不同,硬套一个API会埋下容量误判的坑。

本文转载于:https://www.php.cn/faq/2313917.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。