逆向映射是为了从page得到进程信息,里面有三个比较重要的结构体:
mm_area_struct,
anon_vma_chain,
anon_vma
想象一种复杂的场景
所以其实一个进程对应着很多anon_vma才对
进程A:mmap了16K的匿名页出来,这16k应该是有一个vma,anon_vma结构体,然后四个anon_vma_chain,四个anon_vma_chain是指向了vma,anon_vma;
进程B:是A的子进程,B进程有属于自己的vma,和四个anon_vma_chain,但是4个anon_vma_chain,是在父进程anon_vma->rb_root管理的【这表明啥咧,这表明一个anon_vma中能索引到与之关联的所有的anon_vma_chain,并且通过anon_vma_chain 能够找到所有的vma】【问题1:】【在anon_vma->rb_root中是通过什么管理的索引呢?】
此时B并没有自己anon_vma,但是当次区域发生一次缺页中断时,这个时候,vma就要重新申请一个vma了,并且把这个区域之前的anon_vma_chain link到其他的位置上去。详见do_anonymous_page
之前的queue不清除吗?anon_vma_interval_tree_remove都在哪里调用呢, 只会在unlink_anon_vmas中查看,而这个anon_vmas是
在中断上下文不能插入kprobe了吗?
systemTap在中断上下文中输出不了东西!
0x7000 是多大呀? 0b 111 0000 0000 0000
PROT_READ 和 PROT_WRITE 还是不一样的映射方式;
为啥一个文件以 PROT_READ|PROT_WRITE 和 PROT_WRITE,映射的区间的大小不是一样的?!
如果是以只写映射的,那么值分配分配1M就是1M,但如果是以读/写映射的,那么
理一理,现在有下面几个问题:
1)anon_vma, anon_vma_chain,vma之间的关系;
2)使用不同的标志位去申请PROT_READ|PROT_WRITE,
首先vma和anon_vma之间是一对一的关系,一个vma中映射了4个page,但是4个page指向一个vma_struct,但是每个page的mapping域指向的都是这个anon_vma,这样,当4个page中的一个page因为各种原因要被unmap掉的时候,此时就先找到anon_vma,,然后从里面找我这个page, unmap会不会达到部分解映射的效果呢?
munmap(*addr, length)输入起始地址长度,这总得有一个页表unmap的过程吧?那么unmap除了去掉页表项,并且改变vma->anon_vma_chain 到底是个啥意思啊,好像一个页是放到了anon_vma的红黑树中去了,
munmap->do_munmap-->unmap_region-->free_pgtables -->unlink_anon_vmas,在这里会unlink掉对应的区域【突破口哇】
首先解决第一个问题:fork出来了子进程之后,新的进程的anon_vma变成了,发现16k的mmap区域,4个页,只有一个vma, 一个anon_vma_chain....真是晕了
try_to_unmap rmap_walk_anon(最重要的释放匿名页的函数啦!)
[ anon_vma_interval_tree_insert ]
在try_to_unmap都没用到, 几乎每一次都是伴随着anon_vma_chain出现的,并且
anon_vma->rb_root是一个区间树,在这棵区间树中所有包含这个地址的anon_vma_chain
子进程刚开始时确实会进程到父进程vma里面去,如果发生了一次缺页中断咋整呢?
之前anon_vma_chain 链接到父进程的anon_vma中去了,那现在呢?
一听青啤下肚,想明白了:
1)正常情况下,子进程的vma_anon->anon_vma_chain,链接到父进程的anon_vma->中去
1)正常情况下,子进程的anon_vma_chain结构体rb_node链接到父进程anon_vma->rb_root中,也就是解析page时(page->anon_vma->rb_root)能找到两个anon_vma_chain(父子进程,由于两者指向的vma不同,所以能so easy地找着两个进程的mm_struct; 虽然子进程的anon_vma_chain->rb_node中,但是anon_vma_chain却链接到了属于自己的vma;当一个页发生了缺页中断时,此时page->mapping指向的是自己进anon_vma中去, 在自己的vma中也有自己的vma_area中,并且会有一个属于自己的anon_vma_chain,所以一个vma可能是有两个anon_vma_chain的,其中有一个是链接到自己的anon_vma->rb_root中去,所以当发生了缺页中断之后,这个page只在自己的anon_vma_chain->vma即可啦。明白了,那么有个问题就是anon_vma_chain中有个list,这个list是干啥的咧, vma->anon_vma_chain中记录了这个vma_area中所有的节点,这个节点在不同的anon_vma中安插了,那么这个list用在哪里呢?【在adjust_vma中】
比如进程A和其子进程B 16k的内存映射,刚开始进程B是继承了所有的A的vma,但是此时如果B把这16k全部都munmap掉,此时进程B在A的vma_anon已经没有价值了,因此可以直接去掉,【在munmap时使用】明白了!这个周末。。。。。。。。。。。。。。。。。开了两天车,把这个也看明白了,挺好