tlb刷新的懒惰模式

tlb是一种缓存,缓存的内容是虚拟地址和物理页面的对应关系,每当一个新进程投入运行的时候,tlb就要被刷新,否则就会出现混乱,但是因为linux 的所有进程的内核部分的页面映射是一样的,而且内核线程又不访问用户空间,所以当内核线程运行的时候,tlb是不必马上刷新的,呵呵,这又给内核线程的淫 乱创造了机会。为啥这么说呢?因为tlb没有被刷新,那么比如说内核线程运行前一个用户线程t在运行,其tlb中的虚拟地址a对应物理页面p,那么内核线 程运行后由于没有刷新tlb,那么完全可以访问虚拟地址a,实际上根本就没有重新加载cr3,内核线程还是用的原来进程的页表。
在smp多处理器的机制下,tlb的懒惰刷新模式更有说头,在单处理器的情况之下,tlb的刷新是主动调用的,如果你想刷新tlb,那么你就重新加载 cr3,这个行为只影响到你自己,内核线程并不访问用户空间,那么到底在用谁的页表就无关紧要了,大家的内核部分的页表映射是一样的,因此为了节省开销,就引入了懒惰模式,内核线程不必接受刷新tlb的要求。再smp下,情况就复杂了,试想:一个内核线程抢占了一个用户线程,借用了该用户线程的页目录,页表,然后这个用户线程在内核线程执行的同时被调度到了另外一个cpu上执行,并且在该内核线程退出之前那个用户线程就在另一个cpu上退出了,退出前它肯 定要求刷新所有的tlb,如果此时内核线程运行的cpu还不接受刷新请求的话,那就麻烦了,那个用户线程的页表马上全部被释放,然后借用这些页表的内核线 程将会无穷无尽的发生缺页,而缺页在内核,又不是vmalloc,这是不应该的,最不应该的当前的pgd已经被释放了,该pgd占用的那块内存可能有别的 用途。因此此时即使运行内核线程的cpu也要接受刷新tlb的请求,调用一个叫做leave_mm的函数来回归本位,smp的刷新是靠中断来触发的,而不 仅仅是主动调用的。具体实现懒惰模式的时候需要维持一个数据结构,下面简单说说linux懒惰模式的实现。
每个cpu都有一个每cpu变量来存储懒惰模式的tlb的当前状态,该结构有两个字段,一个是状态值,代表懒惰与否,另一个是一个mm_struct结构,代表当前活跃的mm(对于普通用户线程就是它的mm,对于内核线程就是它借用的用户线程的mm),该mm有一个cpu掩码,指示哪些cpu接受tlb 刷新中断,如果一个内核线程投入运行,那么它就将这个每cpu变量的状态字设置为懒惰模式,然后该cpu在第一次接受到tlb刷新中断请求时将自己从这个 每cpu变量的mm字段的cpu掩码中剥离,这就意味着本cpu在懒惰模式,不再接受刷新tlb的请求。接受tlb刷新请求的cpu掩码一定要明白和谁相关,它是和地址空间相关的,当然是这样的,tlb本质上就是一种地址映射的缓存,于是linux内核的这部分代码理解起来就很简单了,再次强调,tlb刷 新以mm_struct为中心,以cpu为对象在单cpu下直接重载cr3,在smp下则是向此mm_struct的tlb相关的cpu掩码代表的cpu 们发送ipi(处理器间中断)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值