Linux下通过读取/proc/self/status的rss值(单位为页)乘以getpagesize()得RSS字节数,再除以/proc/meminfo中MemTotal(单位kB,需转字节)计算物理内存占用百分比;Windows下用GetProcessMemoryInfo()获取WorkingSetSize、GlobalMemoryStatusEx()获取ullTotalPhys,二者单位均为字节,注意链接psapi.lib及结构体定义要求。

Linux 下用 /proc/self/status 读取物理内存使用量
Linux 系统里没有跨进程的“实时内存占用百分比”API,得自己算:先读当前进程的物理内存用量(RSS),再除以系统总内存。关键数据藏在 /proc/self/status 的 rss: 行(单位是页,不是字节),而系统总内存从 /proc/meminfo 的 MemTotal: 获取。
常见错误是直接用 getrusage() 或 mallinfo() ——它们只反映堆分配或虚拟内存,不等于实际物理驻留内存(RSS)。
-
RSS值在/proc/self/status中形如rss: 123456,需提取数字后乘以getpagesize()得到字节数 -
MemTotal:在/proc/meminfo中单位是 kB,要转成字节再参与计算 - 别缓存
MemTotal,它理论上可能被热插拔内存改变(虽少见,但严谨起见每次读)
Windows 下调用 GetProcessMemoryInfo() + GlobalMemoryStatusEx()
Windows 没有 /proc,得用 Win32 API:GetProcessMemoryInfo() 返回 PROCESS_MEMORY_COUNTERS_EX 结构体里的 WorkingSetSize 字段(等价于 Linux 的 RSS),GlobalMemoryStatusEx() 返回 ullTotalPhys(物理内存总量)。
容易踩的坑是误用 PagefileUsage 或 PeakWorkingSetSize ——前者含换页文件,后者是历史峰值,都不是当前实时物理占用。
- 必须链接
psapi.lib,否则链接失败 -
PROCESS_MEMORY_COUNTERS_EX需定义_WIN32_WINNT>= 0x0501,否则结构体不完整 -
GlobalMemoryStatusEx()返回TRUE才代表数据有效,返回FALSE说明系统太老(XP SP2 以前),应降级处理
跨平台封装时注意单位、精度和更新频率
Linux 和 Windows 的 RSS/WorkingSetSize 定义基本一致(当前驻留物理页),但计算百分比时要注意整数溢出和浮点精度。比如 32 位程序在 64GB 内存机器上,ullTotalPhys 或 MemTotal 可能超 uint32_t 范围。
- 统一用
uint64_t存储字节数,避免截断 - 百分比建议保留 1 位小数(
std::round(rss * 1000.0 / total) / 10.0),避免显示0.0掩盖真实占用 - 不要每毫秒查一次 ——
/proc文件读取和 Win32 API 调用都有开销,100ms 以上间隔更合理
为什么不能依赖 top 或 htop 的 %MEM 输出?
这些工具显示的 %MEM 是 RSS / MemTotal * 100,看似一样,但它们内部做了采样平滑、进程树聚合(比如把子进程 RSS 加进去)、甚至用了不同字段(VSZ 或 Data)——直接复用其逻辑不可靠。
更麻烦的是,top 默认刷新周期是 3 秒,且会动态调整采样策略;你代码里如果 fork+exec+parse 输出,不仅慢,还可能因终端宽度、locale、列顺序变化导致解析失败。
- 不要用
popen("top -b -n1 | grep ...")这类方式,稳定性差、权限受限、启动慢 - 某些容器环境(如 Docker)中
/proc/meminfo的MemTotal是宿主机值,但/proc/self/status的RSS是容器内视角 —— 这种场景下百分比意义有限,需额外判断是否在 cgroup v1/v2 环境下
实际跑起来你会发现,Linux 下读 /proc 几乎无延迟,Windows 下两个 API 调用也很快;真正耗时的反而是字符串解析和除法运算本身 —— 如果你每帧都要查,记得把结果缓存几十毫秒,别让内存监控变成性能瓶颈。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











