《操作系统导论》知识总结 第19章 分页:快速地址转换TLB

操作系统小班正好做到这部分,可以顺便直接写了。

使用分页作为核心机制来完成虚拟内存,可能会带来较高的性能开销。因为将地址空间划分为固定大小的页,要记录各单元地址映射信息。所以地址转换时,需要额外的内存访问来获得映射信息,而每次指令获取显示加载保存都需要额外读取一次内存以得到转换信息。

地址转换旁路缓冲存储器(TLB)也称地址转换缓存,即频繁发生的虚拟地址到物理地址转换的硬件缓存,对每次内存访问,硬件先检查TLB,看看其中是否有期望的转换映射,如果有,就完成转换,由于是硬件完成的,所以速度很快,不需要再访问页表查找页表项中的物理页帧

TLB的基本算法

硬件算法的大体流程如下:

  • 首先从虚拟地址中提取虚拟页号(VPN),然后检查TLB是否有该VPN的转换映射,如果有就有了TLB命中,即TLB有该虚拟页号的转换映射,接下来从TLB中取出物理页帧号(PFN),与虚拟地址中的偏移量结合形成期望的物理地址,并访问内存
  • 如果CPU没有在TLB中找到转换映射(TLB未命中),硬件访问页表来寻找地址转换,并用该转换更新TLB,当TLB更新后,系统会重新尝试该指令,这时TLB中有这个转换映射,内存引用很快得到处理

TLB和其它缓存相似,一般情况下,转换映射会在缓存中(TLB命中),通过缓存来引用内存,只增加了很少的开销,如果TLB未命中,就会带来很大的分页开销,必须先从页表中查找转换映射,如果一段程序中多次TLB未命中,程序的运行就会显著变慢,因此尽可能希望避免TLB未命中

示例:访问数组

如下的一个地址空间,数组从a[0]到a[9]存在于虚拟页06,07,08页中,每个数组元素都有着相对于所处虚拟页的偏移量
在这里插入图片描述
现在有一个循环来访问该地址空间的数组元素:

int sum = 0;
for(int i = 0; i < 10; i++) {
	sum += a[i];
}

通过TLB技术:当访问a[0]时,硬件检查TLB中是否有a[0]虚拟地址的虚拟页号(VPN)的映射,这里是第一次访问该数组,结果是TLB未命中。接下来访问a[1],TLB命中,因为a[0],a[1],a[2]有着同样的虚拟页号,当第一次访问a[0]时,更新了TLB,TLB中有了虚拟页号06到物理页帧的映射转换,接着访问a[3],TLB未命中,访问a[4],a[5],a[6],TLB命中,后续a[7]TLB未命中,a[8],a[9]TLB命中

通过TLB技术引用内存,上述TLB命中率达到了70%,得益于空间局部性,TLB提高了性能,只有对该页的第一个元素的访问才会导致TLB未命中,假设紧接着继续访问该数组,由于时间局部性,即在短时间内对内存再次引用,TLB的命中率会更高,整个程序的运行速度会更快

尽可能使用缓存

缓存技术是计算机系统中最基本的性能改进技术之一,一次又一次地用于让“常见地情况更快”,硬件缓存背后的思想是利用指令和数据引用的局部性,通常有两种局部性:

  • 时间局部性:最近访问过的指令或数据很快会再次访问,如循环中的循环变量或指令
  • 空间局部性:当程序访问内存地址x时,可能很快会访问邻近x的内存,如上述示例中的遍历某数组
    既然缓存技术这么好,为什么不做更大的缓存?更大的TLB?

可是如果想要缓存够快,它就必须小,因为物理限制会起作用,大的缓存注定慢,无法实现目的

由谁来处理TLB未命中

以前是硬件处理TLB未命中,硬件是CISC(复杂指令集计算),为了做到这一点,硬件必须知道页表在内存中的具体位置(通过页表基址寄存器),以及页表的正确格式,发生TLB未命中时,硬件会“遍历”页表,找到正确的页表项,取出想要的地址转换映射,用它来更新TLB,并重试该指令

而现代的体系结构都是RISC(精简指令集计算),发生TLB未命中时,硬件会抛出一个异常,这会暂停当前的指令流,将特权级别提升到内核模式,然后跳转到陷阱处理程序,这段陷阱处理程序是操作系统的一段代码,用于处理TLB未命中,这段代码运行时,会查看页表中的地址转换映射,然后用特权指令更新TLB,并从陷阱返回,此时硬件重试该指令

采用软件管理的方法,主要优势是灵活性,操作系统可以用任意数据结构来实现页表,不需要改变硬件,另一个优势是简单性,硬件只需要抛出异常,操作系统的未命中处理程序会负责剩下的工作

TLB的内容

典型的TLB有32项,64项或128项,并且是全关联的,这意味着一条地址映射可能存在于TLB中的任意位置,硬件会并行的查找TLB,找到期望的地址映射,一条TLB的内容可能是:

在这里插入图片描述
在每条TLB中的其它位中,通常有保护位,用来标识该页是否有访问权限,有效位,用来标识该页是不是有效的地址转换映射,还包括地址空间标识符脏位

上下文切换时对TLB的处理

有了TLB,在进程间切换时,有了一些新问题,即TLB中包含的虚拟到物理地址映射只对当前进程有效,所以发生进程切换时,操作系统和硬件要注意不要误读了之前进程的地址映射

如有两个进程p1和p2,p1的10号虚拟页号映射到了物理页帧100,p2的10号虚拟页号映射到了物理页帧170:
在这里插入图片描述
这时如果不做以区分,硬件分不清哪个项属于哪个进程,如果此刻从p1切换到p2,虚拟页号10是映射到100还是170,这就成了问题所在

为了解决该问题,有两种方法:

  1. 上下文切换时清空TLB,把所有TLB项有效位置0(开销高)
  2. 通过地址空间标识符 ASID,实现跨上下文切换的TLB共享

加上ASID,很清楚不同进程的不同地址转换映射:
在这里插入图片描述
有了ASID,TLB可以同时缓存不同进程的地址空间映射,不用担心冲突,当然硬件也得知道当前是哪个进程在运行,在上下文切换时,必须将某个特权寄存器的值设置为当前进程的ASID

另一种情况,TLB 中某两项非常相似。下表中,属于两
个不同进程的两项,将两个不同的 VPN 指向了相同的物理页。
在这里插入图片描述
如果两个进程共享同一物理页(例如代码段的页),就可能出现这种情况。在上面的例子中,进程 P1 和进程 P2 共享 101 号物理页,但是 P1 将自己的 10 号虚拟页映射到该物理页,而 P2 将自己的 50 号虚拟页映射到该物理页。共享代码页(以二进制或共享库的方式)是有用的,因为它减少了物理页的使用,从而减少了内存开销。

TLB替换策略

TLB中的内容是有限的,需要替换缓存,即向TLB中插入新项时,会替换一个旧项,那应该替换哪一个

有两种常用策略:

  1. 替换最近最少使用的项 LRU,LRU尝试利用内存引用流中的局限性,假定最近没有用过的项,作为被替换的候选项
  2. 随机策略,随机换一个出去,这种策略虽然很简单,但能避免一些极端情况

实际系统的TLB表项

看一个真实的采用软件管理的TLB项:
在这里插入图片描述
MIPS R4000支持32位的地址空间,页大小为4kb,MLPS还有一些标识位,如G(Global),用来指示这个页是不是所有进程全局共享的,如果G=1,救护忽略ASID,C(Coherence)决定硬件如何缓存该页,脏位,表示该页是否被写入了新数据,有效位,告知硬件该项的地址转换映射是否有效

小结

通过增加一个小的,芯片内部的TLB作为地址转换的缓存,大多数内存引用不需要再访问页表,因此极大提高了程序的性能

但是TLB也不能满足所有的程序需求,如果一个程序短时间内访问的页数超出了TLB中的页数,就会产生大量的TLB未命中,运行速度就会变慢,这种现象称为超出TLB覆盖范围,解决这个问题的一种方案是支持更大的页,使TLB的有效覆盖率增加

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值