什么是匿名内存
首先,匿名内存是用户空间虚存的概念,不涉及内核态内存。匿名内存的概念是指一段虚拟内存映射是否有与之相关联的对象,如果没有关联的对象就称为匿名的。
- 匿名映射(anonymous mapping)– 其实就是进程的堆栈等普通内存,它对应的是直接从物理内存分配内存然后建立的映射,没有文件或设备作为后备存储。 匿名映射的内存称为Anonymous Memory, Anonymous Page, Anonymous Buffer…常见的匿名内存有brk()分配的进程数据段、共享内存、mmap()以MAP_ANONYMOUS/MAP_ANON或MAP_PRIVATE标志映射的内存。由于匿名映射没有关联的后备存储,因此回收匿名内存时只能把它们的存储到磁盘交换区,这也是区分匿名内存的一个重要标志。
- 有名映射(memory mapped) – 页表要映射的不是物理内存,而是由某个文件或设备提供的,比如页被映射到一个文件或MMIO内存。此种情况下,需要驱动程序去决定如何建立映射,提供vm_operations_struct结构,即实现vma->vm_ops函数集合。一般情况,这些VMA区域都是用户空间调用mmap()函数以MAP_SHARED映射某个文件时建立的。
内核用vma_is_anonymous()判断vma是否为匿名映射,其实就是检查vma->vm_ops是否为空:
static inline bool vma_is_anonymous(struct vm_area_struct *vma)
{
return !vma->vm_ops;
}
注意,有些人通过查看/proc/<pid>/maps是否给出了映射的名称,并以此来判断是否为匿名映射,这是错误的。比如[stack]、[heap]等都是匿名内存。
$ cat /proc/self/maps
5634845c9000-5634845d1000 r-xp 00000000 fc:01 30 /bin/cat
5634847d0000-5634847d1000 r--p 00007000 fc:01 30 /bin/cat
5634847d1000-5634847d2000 rw-p 00008000 fc:01 30 /bin/cat
563485af6000-563485b17000 rw-p 00000000 00:00 0 [heap]
7fa523b6d000-7fa523e96000 r--p 00000000 fc:01 342 /usr/lib/locale/locale-archive
7fa523e96000-7fa52407d000 r-xp 00000000 fc:01 1059 /lib/x86_64-linux-gnu/libc-2.27.so
7fa52407d000-7fa52427d000 ---p 001e7000 fc:01 1059 /lib/x86_64-linux-gnu/libc-2.27.so
7fa52427d000-7fa524281000 r--p 001e7000 fc:01 1059 /lib/x86_64-linux-gnu/libc-2.27.so
7fa524281000-7fa524283000 rw-p 001eb000 fc:01 1059 /lib/x86_64-linux-gnu/libc-2.27.so
7fa524283000-7fa524287000 rw-p 00000000 00:00 0
7fa524287000-7fa5242ae000 r-xp 00000000 fc:01 1035 /lib/x86_64-linux-gnu/ld-2.27.so
7fa524481000-7fa5244a5000 rw-p 00000000 00:00 0
7fa5244ae000-7fa5244af000 r--p 00027000 fc:01 1035 /lib/x86_64-linux-gnu/ld-2.27.so
7fa5244af000-7fa5244b0000 rw-p 00028000 fc:01 1035 /lib/x86_64-linux-gnu/ld-2.27.so
7fa5244b0000-7fa5244b1000 rw-p 00000000 00:00 0
7ffcacbe9000-7ffcacc0a000 rw-p 00000000 00:00 0 [stack]
7ffcacce5000-7ffcacce8000 r--p 00000000 00:00 0 [vvar]
7ffcacce8000-7ffcaccea000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Thank you ever so for you post.Much thanks again.
Very descriptive post, I liked that bit. Will there be a part 2?