Linux 匿名页的反向映射
我们知道LINUX的内存管理系统中有”反向映射“这一说,目的是为了快速去查找出一个特定的物理页在哪些进程中被映射到了什么地址,这样如果我们想把这一页换出(SWAP),或是迁移(Migrate)的时候,就能相应该更改所有相关进程的页表来达到这个目的。这里我们只讨论没有文件BASE的匿名页的反向映射。网上能查到不少讲解匿名页的反向映射的文章,比如下面的链接:http://lwn.net/Art
我们知道LINUX的内存管理系统中有”反向映射“这一说,目的是为了快速去查找出一个特定的物理页在哪些进程中被映射到了什么地址,这样如果我们想把这一页换出(SWAP),或是迁移(Migrate)的时候,就能相应该更改所有相关进程的页表来达到这个目的。
这里我们只讨论没有文件BASE的匿名页的反向映射。网上能查到不少讲解匿名页的反向映射的文章,比如下面的链接:
http://lwn.net/Articles/383162/
http://larmbr.me/2013/10/08/the-relation-between-vma-anon_vma-and-anon_vma_chain/
这里我用一个例子画了另外一张图,从另一个视角,希望对其中的数据结构的关系能增加一点理解。
这个例子过程是这样的:
那到这个时候,反向映射相关的数据结构关系长成什么样子了呢?Step 1. 创建进程A,在其中malloc()一块内存,生成一个新的VMA,起始虚拟地址如0xb0000000,N多页,写入数据
Step 2. 从进程A fork出进程B,然后只在0xb0000000这一页再次写入数据
Step 3. 从进程B fork出进程C,然后只在0xb0000000这一页再次写入数据
Step 4. 从进程C fork出进程D。什么都 不做。
我们知道一个进程fork出来后,如果不去写BUFFER的话(COW),它会和它的父进程share同一块物理页以节省资源。如上图中的0xb0001000对应到page P1。
如果子进程发生了COW的话,那么内核就不得不给分配一个新的页比如上图中的page P3/P4。
AVC(anon_vma_chain) 被分别挡土挂在两个链表中:
接下来我们来看看这两个链表有什么作用。same_vma:与本进程的这个VMA相关的所有AVC
same_anon_vma:与一个特定的AV相关的所有AVC
1. 如果我想知道P1哪些地方被映射了,我可以这么做:从P1的page.mapping中得到对应的AV,然后在对应的这条蓝色的same_anon_vma中就能知道,ABCD这4个进程都映射了它,从AVC也可以知道是哪个VMA,和具体的虚拟地址了。
2. P4的情况和P1的类似,但是映射它的人只有C和D了。
3. P0的情况和前面的有些不一样,尽管在它对应的same_anon_vma中有ABCD,但是事实上它只在A中映射了。所以我们在便利same_anon_vma链的时候还要进一步确认一下这个page是不是真的映射到了这个VMA中,(vma_address(page, vma))
那我们可不可以把same_anon_vma进一步精确化,使得”只有真正映射了的VMA,对应的AVC在出现在same_anon_vma链中“?如果要达成这样,那么在上面的例子中,B进程COW的时候就要再加出来一个AVC的链了,而且要加到父进程当中去。这样子做下去,也会有额外时间和空间上的开销。可能并不值得。(我就不进一步研究下去了)
那红色的same_vma链做什么用呢?当一个进程要unmap这个vma的时候,可以通过这个链把所有对应的AVC都清理掉。
(待续)
更多推荐
所有评论(0)