在Linux系统中,当我们使用ps、top等工具观察进程状态时,经常会看到VSZ和RSS这两个内存相关的字段。它们都用来描述进程消耗的内存,但统计口径完全不同。搞清楚二者的差异,是分析内存使用、定位泄漏和评估资源限制的基础。

一、VSZ与RSS的基本概念
VSZ是Virtual Memory Size(虚拟内存大小)的缩写。它代表进程所能访问的整个虚拟地址空间的总字节数,包括程序代码、堆、栈、内存映射文件,以及已经申请但还未真正映射到物理内存的部分。Linux采用虚拟内存机制,进程申请内存时通常只是扩展了虚拟地址空间,并不会立刻分配物理页。
RSS是Resident Set Size(常驻内存集)的缩写。它统计的是该进程当前实际驻留在物理内存中的页面总大小。这些页面正被CPU直接访问,没有被交换(swap)到磁盘。需要注意的是,RSS会包含进程使用的共享库内存,如果多个进程共用同一个so文件,这部分物理内存会被每个进程的RSS重复计算。
二、为什么两者数值往往差距很大
很多初学者看到某个进程的VSZ是2GB,而RSS只有200MB,会误以为系统有内存浪费。其实这是因为进程启动时就通过动态链接器映射了大量共享库,同时可能用mmap预留了很大的缓冲区,但绝大多数虚拟页尚未触发缺页中断,也就没有对应物理内存。
另一种情况是进程调用了fork之后,子进程共享父本内存页,此时双方RSS都显示共享部分,但物理内存只有一份。当一方写入时产生写时复制(COW),RSS才会真正分化。因此单纯把系统中所有进程的RSS相加,会严重高估实际物理内存占用。
查看示例
我们可以用ps命令直观对比:
# 查看指定进程的VSZ和RSS,单位KB ps -o pid,vsz,rss,comm -p 1234 # 输出类似 # PID VSZ RSS COMMAND # 1234 2048000 204800 myapp
上面输出中VSZ约为2GB,RSS约为200MB,说明进程虚拟空间大但物理占用小。若RSS长期接近VSZ且持续增长,就要警惕内存泄漏。
三、在内存排查中的实际应用
在容器环境里,像Docker默认用RSS相关的cgroup内存限制来杀进程,而不是VSZ。如果只盯VSZ,会以为容器远远没到上限;实际上RSS超了就会被OOM Killer终止。所以写监控脚本时应优先采集RSS,或读取cgroup的memory.stat。
排查内存泄漏时,可以间隔采样RSS曲线。如果VSZ和RSS同步上涨且RSS不回落,基本确认堆或匿名映射未释放。而若VSZ暴涨RSS不变,多半是预留虚拟空间过多,不一定影响物理内存,但可能触及地址空间限制(如32位程序3GB天花板)。
用代码获取自身内存信息
在C程序中,可以解析/proc/self/statm拿到页数,再乘页面大小:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
long page = sysconf(_SC_PAGESIZE);
FILE *fp = fopen("/proc/self/statm", "r");
if (!fp) return 1;
long total, resident;
// statm第一列为总页数,第二列为常驻页数
fscanf(fp, "%ld %ld", &total, &resident);
fclose(fp);
printf("VSZ: %ld KBn", total * page / 1024);
printf("RSS: %ld KBn", resident * page / 1024);
return 0;
}
该程序读取内核暴露的statm文件,第一列乘页大小即虚拟内存,第二列即常驻集。相比在 shell 里调ps,这种方式方便嵌入服务做自检。
四、常见误区与总结
有人以为RSS就是进程独占的物理内存,这是错的。如前所述,共享库和COW页会让RSS包含非独占部分。若要算进程真实独占量,应结合PSS(按比例占用物理内存)来看,不过PSS不在ps默认输出,需要smem工具。
总体来看,VSZ告诉你进程“要了多少地”,RSS告诉你“盖了多少房”。评估物理资源看RSS,分析地址空间布局或泄漏趋势时参考VSZ。二者配合,才能对Linux进程内存有准确判断。