19.Paging:Faster Translations(TLBs)


19. Paging: Faster Translations (TLBs)

  • Page table存在内存中,因此使用paging的方法需要额外的内存访问,因此比较耗时。问题:如何加速地址翻译并且避免额外的内存访问?需要哪些硬件支持?OS又需要做什么?
  • 方法叫translation-lookaside buffer或者TLB,是MMU的一个部分。其实就是对于经常访问的page frame的一个缓存,因此也叫做address-translation cache。每次进行地址翻译时,先去TLB中找,如果没有再去内存中找。

    19.1 TLB Basic Algorithm

  • 考虑一个简单的linear page table,一个由硬件管理的TLB。

想通过VPN来找到FPN的时候,先去TLB中找,如果找到称为 TLB hit,就可以从TLB中取得FPN。

如果在TLB中没有找到就称TLB miss,这种情况下就和之前一样去内存中找到对应的PTE,从PTEAddr中拿到PTE,再从PTE中拿到PFN,并且更新TLB。

最后重新执行该指令就会hit了。

19.2 Example: Accessing An Array

  • 举个栗子,一个整数数组,有10个4字节的整数,虚拟地址是100开始;地址空间8位,也就是256B,每个 page 16B,也就是说一共有16个page,因此4位VPN,4位offset。

考虑这段C代码:

简单起见,我们只考虑循环的内存访问。

当访问第一个元素a[0]时,虚拟地址100,VPN06,因为是第一次访问,所以 TLB中VPN06对应的FPN肯定是空,TLB miss。当访问第二个元素a[1]时,神奇的事情发生了,TLB hit!为什么呢?因为对于第一个元素,TLB miss之后会去内存中找到VPN06对应的FPN放到TLB中,而第二个元素和第一个元素都是属于VPN06的,因此第二次TLB hit!同理a[2]也是TLB hit!

同理可得,a[3] miss,a[4] hit,a[5] hit,a[6] hit;a[7] miss,a[8] hit,a[9] hit;可以计算出hit比例是70%。我们通过 spatial locality减少了内存访问。如果地址空间再大一点的话,比如4KB,那么整个数组就可以放在同一个page中,那么就只会在第一次miss,其他都是hit。

注意,当我们在该程序中再次访问该数组时,会100%hit,这利用了temporal locality

19.3 Who Handles The TLB Miss?

  • 谁来处理TLB miss?答案有两个:硬件或者OS。

早期,硬件有着complex instruction sets (CISC,complex-instruction set computers),因此由硬件来处miss。硬件通过page table register记住page table的位置,当miss时,从page table中找到PTE再找到PFN。

现代系统一般使用RISC(reduced-instruction set computers),由软件管理TLB,也就是OS。当miss时,OS raises an exception,切换到kernel mode然后jump 到 trap handler,对应的handler里有处理miss的代码,运行这段代码,就会从page table中找到对应地址,使用特权指令更新TLB,然后return from trap ,之后硬件再retry 指令。

  • 现在我们再来看亿点点细节:

第一,这里的return from trap和普通的return from trap指令不太一样。普通的return from trap指令return后是到陷入trap的后面的代码,继续往下执行;而处理TLB miss的return from trap指令return后是return到这条指令开头,需要retry这条指令。
第二,在运行TLB miss handler代码时,在这段代码内要避免造成TLB miss,不然就会一直循环TLB miss。

  • 软件管理TLB的一个好处就是比较灵活,可以使用任意数据结构来实现page table;另一个好处就是简单。

19.4 TLB Contents: What’s In There?

  • 典型的TLB可能包含32、64或128个元素。每个元素长这样:

可以看到和PTE很像,但是other bits又有所不同。

valid bit:表明这个元素的是否有效。

protection bit:表明这个page能被怎样访问。比如读写、读执行等。

等等

19.5 TLB Issue: Context Switches

  • 注意,可能多个进程的PN to PFN信息同时存储在TLB中,对这种情况如何控制?

举个栗子,进程P1正在运行,TLB中保存了P1的VPN10 to PFN 100。进程P2退出了,但是一会可能要切换到P2,TLB中保存了P2的VPN10 toPFN 170:

问题来了,当context switch的时候,如何保证TLB中上一个进程的信息对于即将要运行的进程来讲是无效的呢?硬件和OS又需要做什么来达到上述目的呢?

  • 有很多种做法

一种做法是当context switch的时候就刷新TLB,因此对于下一个进程来讲TLB是空的。可以简单的把valid设置为0。但是这种做法在频繁切换进程时性能较差。

为了解决上述问题,可以通过硬件的支持来让不同的进程之间共享TLB。可以在TLB中加上ASID(address space identifier)字段用于表明当前这个翻译是给哪个进程用的,举个栗子:

这样在context switch的时候就不需要清空TLB了。当然存在两个进程共享page frame的情况:

19.6 Issue: Replacement Policy

  • 对于所有缓存来说,都存在一个共性问题:cache replacement。当缓存满了的时候,如何选择一个来替换?问题来了:在TLB满了的时候,如何选择一个entry来替换?当然目标是尽可能减少miss rate。
  • 最常见的做法是least-recently-used LRU,还有random,各有优劣。

19.7 A Real TLB Entry

  • MIPS R4000的TLB entry如图

32位地址空间,每个page4KB,因此VPN20位,12位offset。但是在图中VPN只有19位,用户的地址空间最多用到一半?(好像是这个意思,原文:user addresses will only come from half the address space (the rest reserved for the kernel))。物理内存64GB,因此PFN24位。

global bit(G):表明该page对于进程是否全局共享,如果是那么就忽略ASID位。

ASID:8位,用于区分不同进程。

Coherence:3位,用于表明硬件是通过何种方式缓存一个page的。

dirty:表明page是否被修改过。

还有一些没有用到。

19.8 Summary

  • TLB用于缓存page table记录的翻译。
  • 但还是存在问题,比如短时间内大量进程切换,导致TLB中缓存的page不够了,那么还是会有很多的TLB miss,超过了TLB coverage,下一章讨论解决方法。

文章作者: foursevenlove
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 foursevenlove !
 上一篇
20.Paging:Smaller Tables 20.Paging:Smaller Tables
20. Paging: Smaller Tables 继续之前的问题,page table可能过大,上一节采用了TLB缓存的方法,这一节来看看不同的方法。问题来了,如何让page table 变小呢?有哪些方法?这些方法又会带来哪些问题?
下一篇 
18.Paging:Introduction 18.Paging:Introduction
18. Paging: Introduction 内存管理有两种,一种是采用变长的chunk,也就是之前讲的segmentation。这章来讲一讲第二种方法,采用定长的chunk,这种方法叫做paging。我们把地址空间分成大小相等unit
  目录