之前写过一篇cgroup内存统计的文章,这里再做一些补充。
几个内存统计相关的变量:
- 
    cache - # of bytes of page cache memory. file cache,包括shm page 
- 
    rss - # of bytes of anonymous and swap cache memory (includes transparent hugepages). 包括所有的anon page和swap cache page 
- 
    mapped_file - # of bytes of mapped file (includes tmpfs/shmem) 当前页表正在映射文件的page(包括shm page) 
- 
    inactive_anon - # of bytes of anonymous and swap cache memory on inactive LRU list. inactive LRU,包括anon page和swap cache page 
- 
    active_anon - # of bytes of anonymous and swap cache memory on active LRU list. 
- 
    inactive_file - # of bytes of file-backed memory on inactive LRU list. inactive LRU,file page 
- 
    active_file - # of bytes of file-backed memory on active LRU list. 
从统计的角度,内核将page分成四类:
(1)anon page:比如malloc分配的page。这类page会影响rss、inactive_anon(active_anon)
(2)file mapped page:文件映射的page,比如通过mmap映射文件。这类page会影响cache、inactive_file(active_file)
(3)shm page:影响cache、inactive_anon(active_anon)
(4)swap cache page:影响rss、inactive_anon(active_anon)
实际上:
cache: file cache page + shm page
rss:  anonymous page + swap cache page
(in)active_anon: anonymous page + swap cache page + shm page
(in)active_file: file cache page
rss + cache = (in)active_anon + (in)active_file
anon page

从上面可以看出,当发生缺页时,如果是anon page,内核会分配一个page,影响rss和active_anon。
示例:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 4000000000   
int main(int argc,char **argv){
    char *shmptr = (char*) malloc(BUF_SIZE);
    memset(shmptr,'\0',1000000000);
    printf("sleep...\n");
    while(1)
        sleep(1);
    exit(0);
}
测试前
cache 59232256
rss 7950336
mapped_file 8232960
inactive_anon 2633728
active_anon 7958528
inactive_file 37187584
active_file 19402752
测试后
cache 59232256
rss 1007697920
mapped_file 8216576
inactive_anon 2633728
active_anon 1007706112
inactive_file 37158912
active_file 19431424
可以看到,rss和active_anon发生了变化。
file mapped page(include shm)

当发生缺页时,如果page是映射文件的page,会分配page,并从磁盘(tmpfs)读取对应的数据,影响cache、(in)active_file。严格来说,shm没有磁盘文件,但shm建立在tmpfs之上,所以,内核也将其与文件同等对待,但page会加到(in)active_anon LRU list。
示例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BUF_SIZE 4000000000   
#define MYKEY 26 
int main(int argc,char **argv){
    int shmid;
    char *shmptr;
    if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1){
        fprintf(stderr,"Create Share Memory Error0m~Z%s\n\a",strerror(errno));
        exit(1);
    }
    if((shmptr =shmat(shmid,0,0))==(void *)-1){
        printf("shmat error!\n");
        exit(1);
    }
    memset(shmptr,'\0',1000000000);
    printf("sleep...\n");
    while(1)
        sleep(1);
    exit(0);
}
程序运行前:
cache 65875968
rss 7643136
mapped_file 8273920
inactive_anon 2633728
active_anon 7651328
inactive_file 43126784
active_file 20107264
程序运行中:
cache 1065881600
rss 7729152
mapped_file 1008279552
inactive_anon 1002635264
active_anon 7737344
inactive_file 43118592
active_file 20119552
程序运行后:
cache 1066213376
rss 7852032
mapped_file 8404992
inactive_anon 1002635264
active_anon 7860224
inactive_file 43356160
active_file 20213760
可以看到,共享内存的分配影响cache、inactive_anon和mapped_file。但值得注意的是,当程序退出之后,mapped_file减小,但inactive_anon并没有变。
实际上,mapped_file表示当前内存页表当前正在映射的page,由于进程退出,页表映射取消,但page并没有free或者swap out,所以inactive_anon不变。
swap cache page

当发生缺页时,如果page对应交换分区,会分配page,并从swap读取数据,影响rss和(in)active_anon。
另外,注意swap cache与(file)cache的区别,前者用于anon page换出时保存数据,后者指file cache page(include shm)。