我们先来看幅图:

Linux内存管理的最底层是buddy内存管理方案,即伙伴算法,管理伙伴算法我们不做详诉,有兴趣的可以自行学习,我们这里只要知道buddy内存池中只能分配2^n个page的内存,比如1,2,4,8……个pages,然而正常使用的时候不会碰巧就需要1,2,4,8……个pages。所以基于buddy内存池,还需要有上一级的内存管理系统,内核里面采用的是slab,slub,slob;而用户空间也有自己的内存管理方案,比如基于glibc的malloc/free内存管理方案。
关于glibc的malloc内存管理方案本文先不做详诉,我们大概了解以下几点,以便对本文的话题有个更加宏观的认识:
如果glibc的内存池中没有内存了,那么malloc就会通过mmap或者brk向buddy申请内存。
free调用不会立即将内存还给buddy,而是会还给glibc的内存池。
如果glibc的内存池中还有足够的内存,那么malloc直接从glibc内存池中分配内存,不会像buddy申请内存。
关于mmap的行为总结下来就是一下几点:
#include
#include
#include
#include #define MMAP_SIZE 0x4000
int main(char *argv[], int argc)
{int i;int tmp;void *addr;char *p;pid_t process_id;process_id = getpid();printf("pid is %d\n", process_id);printf("before mmap\n");getchar();addr = mmap(NULL, MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1, 0);printf("after mmap\n");getchar();p = (char *)addr;for(i=0; i< MMAP_SIZE;i++)tmp = p[i];printf("after read\n");getchar();for(i=0; i
mmap之前的page fault中断以及内存分配情况
执行test程序,打印出before mmap后,通过pidof 找到测试程序的pid为13070,并获取获得如下关键信息:
virtual-machine:~/work$ ps -o maj_flt -o min_flt -p 13070MAJFL MINFL0 77
virtual-machine:~/work$ pmap 13070
13070: ./test
0000000000400000 4K r-x-- test
0000000000600000 4K r---- test
0000000000601000 4K rw--- test
0000000001d10000 132K rw--- [ anon ]
00007f2f56000000 1792K r-x-- libc-2.23.so
00007f2f561c0000 2048K ----- libc-2.23.so
00007f2f563c0000 16K r---- libc-2.23.so
00007f2f563c4000 8K rw--- libc-2.23.so
00007f2f563c6000 16K rw--- [ anon ]
00007f2f563ca000 152K r-x-- ld-2.23.so
00007f2f565d0000 12K rw--- [ anon ]
00007f2f565ef000 4K r---- ld-2.23.so
00007f2f565f0000 4K rw--- ld-2.23.so
00007f2f565f1000 4K rw--- [ anon ]
00007ffc66eab000 132K rw--- [ stack ]
00007ffc66f66000 12K r---- [ anon ]
00007ffc66f69000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]total 4356K
缺页异常数量是77,所有的vma内存分配如上。前的十六进制数字表示分配该段虚拟内存的起始地址。
after mmap之后搜集信息如下:
virtual-machine:~/work$ ps -o maj_flt -o min_flt -p 13070MAJFL MINFL0 77virtual-machine:~/work$ pmap 13070
13070: ./test
0000000000400000 4K r-x-- test
0000000000600000 4K r---- test
0000000000601000 4K rw--- test
0000000001d10000 132K rw--- [ anon ]
00007f2f56000000 1792K r-x-- libc-2.23.so
00007f2f561c0000 2048K ----- libc-2.23.so
00007f2f563c0000 16K r---- libc-2.23.so
00007f2f563c4000 8K rw--- libc-2.23.so
00007f2f563c6000 16K rw--- [ anon ]
00007f2f563ca000 152K r-x-- ld-2.23.so
00007f2f565d0000 12K rw--- [ anon ]
00007f2f565eb000 16K rw--- [ anon ]
00007f2f565ef000 4K r---- ld-2.23.so
00007f2f565f0000 4K rw--- ld-2.23.so
00007f2f565f1000 4K rw--- [ anon ]
00007ffc66eab000 132K rw--- [ stack ]
00007ffc66f66000 12K r---- [ anon ]
00007ffc66f69000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]total 4372K
我们看到page fault没有增加,但是vma增加了一个:
00007f2f565eb000 16K rw--- [ anon ]
那么哪里可以找到实际分配的物理内存的大小呢?可以通过
pmap -x查看,RSS这里是0;方法二,也可以通过可以通过查看/proc/13070/smaps文件来确认
Address Kbytes RSS Dirty Mode Mapping
...
00007f2f565eb000 16 0 0 rw--- [ anon ]
...
---------------- ------- ------- -------
total kB 4372 1328 80
after read之后信息搜集如下:
virtual-machine:~/work$ ps -o maj_flt -o min_flt -p 13070MAJFL MINFL0 81wqq@wqq-virtual-machine:~/work$ pmap 13070
13070: ./test
0000000000400000 4K r-x-- test
0000000000600000 4K r---- test
0000000000601000 4K rw--- test
0000000001d10000 132K rw--- [ anon ]
00007f2f56000000 1792K r-x-- libc-2.23.so
00007f2f561c0000 2048K ----- libc-2.23.so
00007f2f563c0000 16K r---- libc-2.23.so
00007f2f563c4000 8K rw--- libc-2.23.so
00007f2f563c6000 16K rw--- [ anon ]
00007f2f563ca000 152K r-x-- ld-2.23.so
00007f2f565d0000 12K rw--- [ anon ]
00007f2f565eb000 16K rw--- [ anon ]
00007f2f565ef000 4K r---- ld-2.23.so
00007f2f565f0000 4K rw--- ld-2.23.so
00007f2f565f1000 4K rw--- [ anon ]
00007ffc66eab000 132K rw--- [ stack ]
00007ffc66f66000 12K r---- [ anon ]
00007ffc66f69000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]total 4372K
缺页异常增加了四个,因为有4个page被读了嘛!然而Rss没有增加,说明根本没有分配实际的物理内存,完全符合预期。
after write之后信息搜集如下:
virtual-machine:~/work$ ps -o maj_flt -o min_flt -p 13070MAJFL MINFL0 85
virtual-machine:~/work$ pmap -x 13070
13070: ./test
Address Kbytes RSS Dirty Mode Mapping
...
00007f2f565eb000 16 16 16 rw--- [ anon ]
...
---------------- ------- ------- -------
total kB 4372 1344 96
新增了四个page fault,并且RSS是16K,此时才真正的分配了物理内存。
通过查看/proc/13070/smaps也发现如下:
7f2f565eb000-7f2f565ef000 rw-p 00000000 00:00 0
Size: 16 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 16 kB
Pss: 16 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 16 kB
Referenced: 16 kB
Anonymous: 16 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
ProtectionKey: 0