/proc/meminfo 中的 MemTotal 是内核识别的物理内存总量,即硬件实际可用上限(单位 kB),需转换为 GiB;它不等于插槽总和(因 BIOS/UEFI 预留、内核占用等扣减),也不代表进程可分配量。

Linux 下用 /proc/meminfo 查物理内存上限(非虚拟地址空间)
很多人混淆“系统最大内存”和“进程可分配内存”,/proc/meminfo 给出的是当前内核识别到的物理内存总量,也就是硬件实际可用上限(不含预留、未启用或热拔插未激活部分)。它不反映单个进程能用多少——那是虚拟地址空间的事。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 读取
/proc/meminfo中的MemTotal:行,单位是 kB,需转为字节或 GiB;注意该值可能略小于物理插槽总和(BIOS/UEFI 预留、内核自身占用、iommu 映射等都会扣减) - 不要依赖
MemFree或Available判断“最大”,它们是动态值;MemTotal才是稳定基准 - 若系统启用了 memory cgroup 限流(如 Docker 容器),
/sys/fs/cgroup/memory/memory.limit_in_bytes可能比MemTotal更小,此时它才是该进程实际可见的“最大内存”
Windows 上调用 GetPhysicallyInstalledSystemMemory() 获取插槽级物理内存
这个 API 返回的是 BIOS 报告的已安装物理内存容量(单位 KB),和 Linux 的 MemTotal 不同:它不经过内核裁剪,也不扣除任何保留区域,更接近“主板上插了多少条 DDR4”这一原始事实。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须链接
kernel32.lib,函数声明在windows.h中;返回值是BOOL,真实数据通过*lpTotalMemoryInKilobytes输出 - 它不反映当前是否所有内存都被启用(比如 BIOS 关闭了部分通道,或开启了内存压缩),也不包含任何虚拟化层限制
- 如果程序运行在 Hyper-V 虚拟机中,该函数返回的是虚拟机配置的内存上限,而非宿主机物理总量
C++ 程序里不能靠 std::numeric_limits<size_t>::max()</size_t> 得到“系统最大内存”
这是最常见的误解:size_t 最大值只代表指针能寻址的虚拟地址空间宽度(例如 x86-64 下通常是 2^48 或 2^57 字节),和物理内存、操作系统允许分配的内存完全无关。试图用它判断“最多能 malloc 多少”一定会失败。
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
malloc()或new失败时返回nullptr,不是因为触达size_t::max(),而是brk/mmap系统调用被拒绝(ENOMEM) - 在 64 位系统上,
size_t宽度远大于当前任何服务器的物理内存(EB 级 vs TB 级),拿它当内存上限毫无意义 - 若真要估算单进程可用堆上限,应查
/proc/self/status的VMPeak或 Windows 的GetProcessMemoryInfo(),但这些仍是运行时快照,非理论最大值
跨平台封装要注意:没有统一的“系统最大内存”概念
不同平台对“最大内存”的定义粒度不同:Linux 关注内核感知的物理内存,Windows 关注 BIOS 报告的安装容量,而容器/云环境还要叠加 cgroup、quota、VM 配额等多层限制。强行抽象成一个函数容易误导调用方。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 不要写
get_system_max_memory()这种接口;按场景拆分:是做资源预检?还是配置默认缓存大小?或是诊断 OOM 原因?每种需求对应不同数据源 - 若用于初始化缓存,默认设为物理内存的 25%~50% 比硬编码“最大值”更稳妥;记得检查
/sys/fs/cgroup/memory/是否存在,优先读取其中的memory.limit_in_bytes - 在 CI/CD 或容器部署中,
MemTotal和GetPhysicallyInstalledSystemMemory都可能失效——这时真正起作用的是调度器下发的 limits(如 Kubernetes 的resources.limits.memory)
物理内存总量只是起点,真正影响你 malloc 成败的,往往是 cgroup 限流、交换空间配置、内核参数(如 vm.overcommit_memory)、甚至 SELinux 策略。别只盯着一个数字看。


















