windows下用getprocessmemoryinfo获取工作集大小最可靠,需链接psapi.lib并包含psapi.h,workingsetsize字段返回当前驻留物理内存字节数;linux下读/proc/self/statm第二列乘页大小近似rss。

Windows下用GetProcessMemoryInfo获取工作集大小
在Windows平台,GetProcessMemoryInfo 是最直接、可靠的方式获取当前进程的工作集(Working Set)大小,即当前驻留在物理内存中的页数。它属于PSAPI库,需链接 psapi.lib 并包含头文件 <psapi.h></psapi.h>。
- 调用前必须用
OpenProcess获取当前进程句柄,推荐使用GetCurrentProcess()(返回伪句柄,无需权限检查) -
PROCESS_MEMORY_COUNTERS结构体中的WorkingSetSize字段单位是字节,不是页数 - 该值反映的是“当前可立即访问的物理内存页总量”,不包括被换出(paged out)或共享但未映射的页
- 若程序以低完整性级别运行(如UAC限制下),仍可读取自身工作集,无需特殊权限
Linux下通过/proc/self/statm读取RSS近似值
Linux没有严格等价于Windows“工作集”的API,但 /proc/self/statm 的第一个字段(size)和第二个字段(resident)常被用作参考:resident 表示当前驻留物理内存的页数(RSS),单位是页(通常4KB),它最接近“工作集”语义。
- 读取时需用
sysconf(_SC_PAGESIZE)转换为字节数,不能硬编码4096——某些ARM或RISC-V系统页大小不同 -
statm中的resident不包含共享库中被其他进程锁定的页,也不排除刚被换入但尚未访问的页,因此是近似值 - 避免频繁轮询——每次读取都触发一次内核态上下文切换,高频采集会显著影响性能
- 注意:该文件内容是空格分隔的7个数字,顺序固定,不要依赖字段名解析
跨平台封装要注意的陷阱
试图写一个统一接口时,容易忽略底层语义差异导致误判。Windows的 WorkingSetSize 和 Linux 的 RSS 数值通常不相等,即使同一时刻测量。
- Windows工作集包含“可交换但未换出”的私有提交页;Linux RSS只统计实际映射且未换出的物理页
- 两者都不计入被
mlock()锁住但尚未访问的页(Linux)或VirtualLock()锁定但未触碰的页(Windows) - 若用于内存监控告警,建议分别设定平台阈值,而不是统一用“>100MB”这种绝对值判断
- C++17及以上可用
std::filesystem::read_symlink("/proc/self/exe")辅助判断是否运行在Linux,但别依赖__linux__宏做运行时分支——编译平台 ≠ 运行平台
为什么GetWorkingSetSize()不是标准C++函数
因为C++标准库不暴露操作系统级内存管理细节,GetWorkingSetSize() 根本不存在——这是常见误解,源于把第三方库或旧文档函数名记混了。
- Windows SDK里只有
GetProcessMemoryInfo,没有独立的GetWorkingSetSize - Boost.Process 或 Qt 等库也未提供跨平台工作集查询接口,它们要么封装上述原生API,要么干脆不支持
- 试图用
std::malloc_usable_size或mallinfo替代?不行——这些只反映堆分配器内部状态,与物理内存驻留无关 - 如果项目强制要求“纯标准C++”,那就无法获取该指标,得接受这个事实
statm 的页大小动态性,以及Windows下工作集受系统内存压力实时压缩的特性——同一进程两次采样可能差几倍,这不是bug,是设计使然。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











