windows下用getprocessmemoryinfo获取workingsetsize最可靠,linux下读/proc/self/statm第二列resident乘以页大小得rss;二者均反映当前驻留物理内存,但语义不完全等价。

Windows下用GetProcessMemoryInfo获取工作集大小
在Windows平台,GetProcessMemoryInfo 是最直接、可靠的方式获取当前进程的“工作集”(Working Set)大小,即当前驻留在物理内存中的页数量。它属于PSAPI库,需链接 psapi.lib 并包含 <psapi.h></psapi.h>。
常见错误是误用 GetProcessWorkingSetSize(已废弃且返回值不可靠),或混淆“工作集”与“私有工作集”“提交大小”等指标。
- 调用前必须用
GetCurrentProcess()获取有效句柄,不能传NULL或无效句柄 -
PROCESS_QUERY_INFORMATION权限是必需的,但GetCurrentProcess()默认具备该权限,无需额外OpenProcess - 返回的
PROCESS_MEMORY_COUNTERS结构中,WorkingSetSize字段单位是字节,不是页数 - 注意结构体大小:必须设置
cb成员为sizeof(PROCESS_MEMORY_COUNTERS),否则 API 返回失败(GetLastError()为ERROR_INVALID_PARAMETER)
#include <psapi.h>
#include <iostream><p>size_t GetCurrentWorkingSetSize() {
PROCESS_MEMORY_COUNTERS pmc = {};
pmc.cb = sizeof(pmc);
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
return pmc.WorkingSetSize;
}
return 0;
}</p></iostream></psapi.h>
Linux下用/proc/self/statm读取近似工作集
Linux 没有严格等价于 Windows “工作集”的用户态接口,/proc/self/statm 提供的是驻留内存(RSS)的粗略估计,它反映当前映射且未被换出的物理页数,行为上最接近工作集语义。
注意:statm 第二列(resident)单位是页(通常为 4KB),不是字节;且该值含共享页(如 libc),不完全等同于进程独占工作集。
- 不要解析
/proc/self/status中的VmRSS——它和statm第二列本质相同,但字符串解析开销更大 - 避免频繁轮询
/proc/self/statm,尤其在性能敏感路径中;每次读取需系统调用+文件 I/O - 若需更高精度(如排除共享页),需结合
/proc/self/pagemap和/proc/self/maps手动统计,但代价高、需 root 权限且内核版本依赖强
#include <fstream>
#include <string><p>size_t GetLinuxRSSBytes() {
std::ifstream f("/proc/self/statm");
if (!f.is_open()) return 0;
long size, resident;
f >> size >> resident;
return static_cast<size_t>(resident) * static_cast<size_t>(getpagesize());
}</size_t></size_t></p></string></fstream>
跨平台封装时的关键取舍
没有真正跨平台的“工作集”定义,强行统一接口容易掩盖差异。例如 macOS 的 task_info(TASK_VM_INFO)返回的 phys_footprint 更接近“压缩后驻留内存”,而 Linux RSS 不含 swap-backed 页但含共享页。
- 若目标是监控内存压力趋势,用 RSS(Linux)或 WorkingSetSize(Windows)足够,二者都随实际物理内存占用变化
- 若用于资源配额或 OOM 判定,必须区分平台:Windows 应优先看
PrivateUsage(PROCESS_MEMORY_COUNTERS_EX),Linux 应看/sys/fs/cgroup/memory/memory.usage_in_bytes(容器环境)或MemAvailable(系统级) - 不要把
WorkingSetSize当作“可用内存上限”——它可瞬时增长,且受系统策略(如工作集修剪)影响,不具备稳定性
调试时发现数值异常的排查点
拿到的数值远小于预期(如空进程报告几 MB)或剧烈抖动,大概率不是代码错,而是理解偏差或系统行为干扰。
- 刚启动的进程工作集极小,只有代码段和初始堆栈加载;大量分配后才增长,但未必立刻驻留——缺页中断触发后才计入
- Windows 上启用“工作集限制”(
SetProcessWorkingSetSize设为-1)会强制收缩,导致WorkingSetSize异常偏低 - Linux 下启用透明大页(THP)可能导致 RSS 跳变;启用
memcg时,statm仍读全局值,需切到 cgroup 路径下读取 - 多线程频繁分配/释放小对象易引发
malloc内存池缓存,这部分内存可能长期驻留但不被statm立即反映
工作集本身是操作系统动态维护的近似值,不同平台采集时机、统计粒度、是否含共享页都不同,拿来做绝对比较或阈值判断前,务必在目标环境中实测验证其行为边界。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











