1.内核页表问题
kmalloc与kmem_cache_alloc之后的页表
实际上前者是后者实现的,而且物理地址连续内核在执行kmalloc的时候,并没有发现有设置页表的行为,实际上是在系统启动的时候在 kernel_physical_mapping_init里面设置好的,3g到3g+896m的地方属于物理影射,和物理地址是一一对应的,所以可以直 接使用,但是既然物理映射是一一对应的而且拥有页表,那么岂不是任何访问内核物理映射的代码都不会缺页,是这样的,这不会有任何问题,刑不上大夫,你既然能到内核空间,就证明你已经拥有了一定的特权,只要符合约定就不会出问题,
就比如说谁也没有规定你不能在中断处理里面调用schedule,而且 你完全可以在没有调用spin_lock的情况下调spin_unlock,会出问题吗?出问题的是你自己,这个世界不会因为刀可以杀人就不用刀切菜了。启动之后,任何kmalloc或kmem_cache_alloc的调用都从伙伴系统把页拉出来,页表已经设置好了。
vmalloc后的页表
这个分配函数页后,必须显式地更新页表,因为vmalloc分配的页面不属于物理映射,而是属于3g+896m后的vmalloc区域的映射区域,在vmalloc后必须set_pte而vfree后必须清除页表。
但是问题来了,在vmalloc后虽然设置了vmalloc的页表,但是并没有清除原来的页表(为了使得讨论方便我这里故意假设vmalloc在 3g+896以下分配),也就是两个页表对应同一个页面(物理映射和vmalloc映射),事实上是这样的,但是虽然理论上是这样,但实际上又没有意义 呢?实际上没有意义,我们知道,访问一个地址是因为我们需要它,很多情况下这个地址是一个数据结构,而包括数据结构在内的所有内存都来自伙伴系统,如果一个地址已经被物理地址映射了,说明它已经不在伙伴系统空闲链表里面了,那么同样来自伙伴空闲页链的vmalloc还会得到相同的页面吗?原则上你完全可以并行访问这两个虚拟地址,但事实上这将是一种自虐行为。
2.用户页表问题
用户页表问题是简单的,比如在mmap系统调用里面,修改的只是一些vm区域的字段,比如start,end之类的,真正的页表设置将推迟到缺页的发生。但是在umap时必须清除页表。
事情真的就是这样吗?事实上就是这样,但是要注意的是,这个时候最少两个地方映射着用户的物理内存,一个是用户空间,一个是初始化时候的物理映射。
kmalloc与kmem_cache_alloc之后的页表
实际上前者是后者实现的,而且物理地址连续内核在执行kmalloc的时候,并没有发现有设置页表的行为,实际上是在系统启动的时候在 kernel_physical_mapping_init里面设置好的,3g到3g+896m的地方属于物理影射,和物理地址是一一对应的,所以可以直 接使用,但是既然物理映射是一一对应的而且拥有页表,那么岂不是任何访问内核物理映射的代码都不会缺页,是这样的,这不会有任何问题,刑不上大夫,你既然能到内核空间,就证明你已经拥有了一定的特权,只要符合约定就不会出问题,
就比如说谁也没有规定你不能在中断处理里面调用schedule,而且 你完全可以在没有调用spin_lock的情况下调spin_unlock,会出问题吗?出问题的是你自己,这个世界不会因为刀可以杀人就不用刀切菜了。启动之后,任何kmalloc或kmem_cache_alloc的调用都从伙伴系统把页拉出来,页表已经设置好了。
vmalloc后的页表
这个分配函数页后,必须显式地更新页表,因为vmalloc分配的页面不属于物理映射,而是属于3g+896m后的vmalloc区域的映射区域,在vmalloc后必须set_pte而vfree后必须清除页表。
但是问题来了,在vmalloc后虽然设置了vmalloc的页表,但是并没有清除原来的页表(为了使得讨论方便我这里故意假设vmalloc在 3g+896以下分配),也就是两个页表对应同一个页面(物理映射和vmalloc映射),事实上是这样的,但是虽然理论上是这样,但实际上又没有意义 呢?实际上没有意义,我们知道,访问一个地址是因为我们需要它,很多情况下这个地址是一个数据结构,而包括数据结构在内的所有内存都来自伙伴系统,如果一个地址已经被物理地址映射了,说明它已经不在伙伴系统空闲链表里面了,那么同样来自伙伴空闲页链的vmalloc还会得到相同的页面吗?原则上你完全可以并行访问这两个虚拟地址,但事实上这将是一种自虐行为。
2.用户页表问题
用户页表问题是简单的,比如在mmap系统调用里面,修改的只是一些vm区域的字段,比如start,end之类的,真正的页表设置将推迟到缺页的发生。但是在umap时必须清除页表。
事情真的就是这样吗?事实上就是这样,但是要注意的是,这个时候最少两个地方映射着用户的物理内存,一个是用户空间,一个是初始化时候的物理映射。
综上,真正修改页表就在那么几个点,分别为:系统启动,用户缺页,vmalloc,仔细看一下do_pagefault的代码,涉及内核缺页,就是vmalloc导致的,这涉及到另一个问题,就是init_mm的懒惰更新。
本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1274052