Linux进程中的RSS和VSZ
64位Linux系统中虚拟内存空间大小
我们都知道32位系统的虚拟内存空间大小是2^32B,也就是4GB。但是,64位系统的虚拟内存空间的大小并不是2^64B,而是2^48B,也就是256TB。而64位系统支持的物理内存大小最高为2^46B,也就是64TB(这当然远超出了目前我们日常使用的物理内存的规格)。
查看Linux系统支持的物理内存和虚拟内存大小的方法:
cat /proc/cpuinfo | grep 'address sizes'
RSS
RSS is the Resident Set Size and is used to show how much memory is allocated to that process and is in RAM.
RSS是实际分配给进程使用的物理内存。
VSZ
VSZ is the Virtual Memory Size. It includes all memory that the process can access.
VSZ是进程的占用的虚拟内存的大小,也就是进程能够访问到的内存空间大小(实际可能尚未在物理内存中分配)。
下面我们通过一个小实验,来加深对RSS和VSZ的理解。
- 我们首先打印出进程的RSS和VSZ大小。
- 然后向系统申请40MB的内存,此时我们并不向其中读取或者写入数据,打印此时进程的RSS和VSZ的大小。
- 之后我们向申请的内存中写入数据,再次打印RSS和VSZ的大小。
C代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int get_proc_rss(pid_t pid){
char buf[128];
sprintf(buf, "ps aux | awk \'{if ($2 == \"%d\") print $6}\'", pid);
FILE *fp;
fp = popen(buf, "r");
char num_buf[16] = { 0 };
fgets(num_buf, 16, fp);
int res = atoi(num_buf);
return res;
}
int get_proc_vsz(pid_t pid){
char buf[128];
sprintf(buf, "ps aux | awk \'{if ($2 == \"%d\") print $5}\'", pid);
FILE *fp;
fp = popen(buf, "r");
char num_buf[16] = { 0 };
fgets(num_buf, 16, fp);
int res = atoi(num_buf);
return res;
}
void print_vsz_rss(const char *tag){
pid_t pid;
pid = getpid();
printf("%s : VSZ = %dKB RSS = %dKB\n", tag, get_proc_vsz(pid), get_proc_rss(pid));
}
int main(){
print_vsz_rss("start");
int *num = malloc((10*1024*1024)*sizeof(int));
print_vsz_rss("malloc");
for(int i=0;i<10*1024*1024;i++){
num[i] = i;
}
print_vsz_rss("touch");
return 0;
}
运行,输出的结果为:
start : VSZ = 4328KB RSS = 832KB
malloc : VSZ = 45292KB RSS = 832KB
touch : VSZ = 45292KB RSS = 42372KB
首先我们看到,向系统中申请40MB内存之后,VSZ增加了大约40MB,而RSS并没有发生变化,而在我们向申请的内存写入数据之后,RSS的值就增加为与VSZ相同的数值。
在上一个实验中,我们往申请的内存中的所有区域都写入了数据。这次我们考虑只向申请的内存中的一半区域写入数据,输出的结果为:
start : VSZ = 4328KB RSS = 792KB
malloc : VSZ = 45292KB RSS = 792KB
touch : VSZ = 45292KB RSS = 23600KB
可以看到,向一半的内存区域写入数据之后,RSS增加为与VSZ一半相当的数值。
结论
VSZ是进程的占用的虚拟内存的大小,也就是进程能够访问到的内存空间大小(实际可能尚未在物理内存中分配)。RSS是实际分配给进程使用的物理内存。也就是说RSS是按需分配的,实际上,只有当进程实际访问到相应的内存地址时,操作系统会将虚拟空间地址映射到物理内存空间中(通过页表与MMU硬件实现),若此时虚拟地址与物理内存尚未建立映射,就会产生一个缺页异常(Page Fault),操作系统处理缺页异常,建立虚拟地址与物理内存之间的映射,此时物理内存才是真正地分配到了进程的手中,也就是RSS的增长。
参考链接:
https://eli.thegreenplace.net/2018/measuring-context-switching-and-memory-overheads-for-linux-threads/
https://stackoverflow.com/questions/7880784/what-is-rss-and-vsz-in-linux-memory-management