欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

每天3分钟操作系统修炼秘籍(11):页翻译——快速地址转换

程序员文章站 2022-08-19 19:28:49
"点我查看秘籍连载" 页翻译:快速地址转换 虽然操作系统通过页表也能将虚拟页翻译成内存中对应的页帧,但是它仍然很慢。另一方面,如果访问每个页都需要操作系统来参与帮忙翻译,这会频繁陷入内核,效率是非常低的。所以,这里再次将任务交给硬件CPU去做。 提示:操作系统将底层任务交给硬件提高效率 前文介绍段的 ......

页翻译:快速地址转换

虽然操作系统通过页表也能将虚拟页翻译成内存中对应的页帧,但是它仍然很慢。另一方面,如果访问每个页都需要操作系统来参与帮忙翻译,这会频繁陷入内核,效率是非常低的。所以,这里再次将任务交给硬件cpu去做。

提示:操作系统将底层任务交给硬件提高效率

前文介绍段的虚拟地址翻译,以及这里介绍的页翻译,本都可以由操作系统完成,但是操作系统参与太多效率会非常低,这时候都将任务交给操作系统的好伙伴——硬件(cpu)来完成,这会减少大量的上下文切换,因为不用再陷入内核了。

不仅如此,磁盘io本也是可以由操作系统参与完成的,但速度会更慢,所以也将io任务交给了硬件(硬盘)去完成。此外,还有网卡、显卡等等。

所以可以做个总结,只要频繁进行底层操作的任务,一般都会交给硬件而绕过操作系统内核(因为绕过内核,这类任务也常称为内核旁路操作),它们的原理都一样。而要交给硬件,硬件肯定要支持这类操作。

cpu对页做快速地址转换,其全称为translation-lookaside buffer(tlb),即地址转换旁路缓冲。快速地址转换之所以称为tlb,这是历史原因造成的。但是否注意到旁路缓冲这几个字?即绕过内核的缓冲,也就是硬件中的缓冲。

所以,cpu对页做快速地址转换是借助cpu的高速缓冲区完成的,而且使用的l1级缓存(离cpu核心最近的缓存)和l2级缓存(比l1缓存稍慢),翻译速度可想而知有多快。

这里以最简单的方式描述下快速地址转换涉及到的一些过程。

每天3分钟操作系统修炼秘籍(11):页翻译——快速地址转换

虽然cpu的高速缓存速度非常快,但与之对应的是缓存空间非常小,所以只能保存有限数量的翻译信息。如果高速缓冲区缓存的翻译信息数量已满,当访问缓存中不存在翻译信息的页,就只能从内存的多级页表中读取翻译信息,因为这条翻译信息也要缓存到高速缓冲区,所以只能从高速缓冲区中踢掉之前的一条翻译信息。那么踢掉哪一项呢?于是缓存替换策略算法就派上用场了,例如随机踢掉一项的随机替换算法,踢掉最近最少访问的那项的lru算法,等等。

这里给一个访问数组的示例,来帮助理解tlb带来的好处。如下图是数组a中10个元素的存放方式,总共存放在3个虚拟页中。

每天3分钟操作系统修炼秘籍(11):页翻译——快速地址转换

如果依次去访问这10个数组元素,首先访问a[0]时高速缓冲区中没有缓存相关的翻译信息,所以需要从内存中去读取vpn 02页的翻译信息并缓存在高速缓冲区中,然后到对应的物理内存中去取得该元素的值。但是当访问a[1]和a[2]的时候就能够从高速缓冲区中受益,因为这两个元素都在vpn 02页中,而该页的翻译信息已经缓存了。

同理,访问新页中a[03]和a[7]的时候,需要先从内存中读取页vpn 03和vpn 04的翻译信息并缓存下来,之后再访问页中其它元素的时候就可以直接从缓存中取得翻译信息,直接找到物理内存中的值。

这里可以做个假设,假如每页的大小足够大,数组a中的元素可以全部存放在同一个页中,那么缓存的效果显然更好。但页过大,容易造成大量的页空间浪费,因为内存的操作单元是页,如果一个100k的页只存放了1k的数据,也只能读取这100k,并且剩余99k空间被浪费,这种浪费称为内部碎片

提示:空间的外部碎片和内部碎片

这是空间管理的两个经常出现概念。

内部碎片是给空间按固定大小划分成块或页后,块内或页内的空间没有完全利用导致有一部分空间浪费,这种称为内部碎片,即页内或块内的空间碎片。一般使用填充因子或页密度来描述页的空间使用率是高还是低。内部碎片有好处也有坏处,坏处是浪费了一点空间,但这是无法避免的,好处是每页都留下了空闲空间,如果程序支持的话(例如数据库),以后该页可以继续存入新数据。

外部碎片是因为给空间划分了不同大小的区段(即分段或分区)后,随着空间的分配和释放,导致空间的不连续(即出现了空间孔洞)。例如3段连续空间大小分别为10k、20k、10k,如果中间的20k已被使用而左右两个10k是空闲的(这是可能的,空间可以在使用后释放),即使现在总共有20k空闲空间,但如果想要申请15k空间,结果要么失败,要么通过链表将不连续的空间链起来,不同程序处理方式不一样。所以,外部碎片过多的负面影响非常大,要么因无法分配空间导致程序异常终止,要么因为访问空间时要通过链表跳转的重定位而严重影响性能。