Linux下用/proc/self/status读取VmRSS和VmSize可准确获取进程当前物理内存占用(单位KB)与虚拟内存总大小(单位KB),二者均为内核实时维护的键值对字段,需逐行解析并跳过单位后提取数值,不可缓存或依赖/stat等不稳定接口。

Linux下用/proc/self/status读取RSS和VMSize
Linux进程的内存使用最可靠的方式是解析/proc/self/status,它实时反映当前进程的内存快照。关键字段是VmRSS(实际物理内存占用,单位KB)和VmSize(虚拟内存总大小,单位KB)。注意:这不是C++标准能力,必须依赖系统接口。
常见错误是直接读/proc/self/stat——它字段位置易变且无字段名,维护成本高;而status是键值对格式,稳定可解析。
- 用
std::ifstream打开/proc/self/status,逐行查找以VmRSS:或VmSize:开头的行 - 每行末尾的
KB要跳过,用std::stoll()提取数值 - 不要缓存该文件内容——它每毫秒都可能变化,每次需要时重新读取
- 若程序以
setuid运行,/proc/self/可能不可读,需提前检查权限
Windows用GetProcessMemoryInfo获取WorkingSetSize
Windows没有统一的/proc等价物,必须调用psapi.h中的GetProcessMemoryInfo。返回结构体PROCESS_MEMORY_COUNTERS里的WorkingSetSize字段最接近Linux的RSS,表示当前驻留内存(单位字节)。
容易忽略的是:这个API在MinGW或某些旧SDK中可能未声明,需确保链接psapi.lib,且编译时定义_WIN32_WINNT≥0x0501。
立即学习“C++免费学习笔记(深入)”;
- 先用
GetCurrentProcess()获取当前进程句柄 - 调用
GetProcessMemoryInfo前,确保PROCESS_MEMORY_COUNTERS结构体cb成员已设为sizeof(PROCESS_MEMORY_COUNTERS),否则返回失败 -
PagefileUsage字段对应虚拟内存使用量,但不等于Linux的VmSize,因Windows分页机制不同 - 该函数本身开销极小,但频繁调用(如每毫秒)仍会引入轻微性能抖动
C++标准库无法直接获取内存用量
别指望std::allocator、new重载或std::pmr能告诉你整个进程用了多少内存——它们只管自己分配的那部分,且不跟踪释放后是否归还给OS。很多开发者误以为重载operator new并计数就能得到准确RSS,结果发现数字远小于/proc/self/status显示值。
根本原因是:glibc/musl的malloc(如ptmalloc)会缓存已释放的内存块,长期不交还给内核;而C++运行时自身(如libstdc++的异常处理表、iostream缓冲区)也占内存,但不在用户重载范围内。
- 即使你统计了所有
new调用,漏掉静态存储期对象、线程局部存储、动态链接库的私有数据段 -
mallinfo或malloc_stats只反映堆管理器视角,和OS看到的RSS不是一回事 - 跨平台封装库(如
boost::process)也不提供此功能——它本质仍是调用底层系统API
跨平台封装要注意字段语义差异
写一个跨平台函数返回“当前内存使用”时,不能简单返回同一单位的数字——Linux的VmRSS和Windows的WorkingSetSize虽都指物理内存驻留量,但计算时机和精度不同:Linux是内核精确统计,Windows受页面调度影响可能滞后几秒。
更麻烦的是,macOS既没/proc也没psapi,得用task_info(mach/task_info.h),返回的phys_footprint才是等效指标,而resident_size已被弃用。
- 不要用宏定义统一返回“MB”,因为不同系统误差范围不同(Linux误差±4KB,Windows可能±1MB)
- 若用于监控告警,建议同时采集多个指标:RSS + 虚拟内存大小 + 页面错误次数(
minflt/majflt),单一数值容易误判 - 容器环境(Docker/K8s)中,
/proc/self/status看到的是cgroup限制内的值,需额外读/sys/fs/cgroup/memory/memory.usage_in_bytes
真正难的不是读哪个文件或调哪个函数,而是理解每个数字背后代表的内存生命周期阶段——驻留?映射?提交?不同系统连术语都不完全对齐。


















