《操作系统 - 清华大学》4 -3:非连续内存分配:页表——概述、TLB

文章目录

0.目的


怎么有效地实现这种转换机制? 前面已经提到了有页表,但页表怎么来实现?怎么能实现高效?怎么能实现的更加节省空间?

操作系统和计算机硬件相互配合才能共同完成的目标,所以把页表专门拎出来做更深入的讲解。

1.页表结构

先看看页表结构,页表其实是大数组,一般来说它的索引就是它的页号,索引所对应页表项的内容主要存的就是帧号(frame number), 对应关系看起来好像比较直观。CPU 会查这个页表在什么地方,它的起始地址在哪?通过 page number 算出它的 index,寻址到对应的页表项,把相应 frame number 给取出来,那么就可以把 frame number 叠加上 offset,形成物理地址。

除了 frame number 之外,还有一些 bit,bit 是一些特殊的用途,可以表示这个页表项是否是一个合法的页表项,什么叫合法,就是这个页对应的物理页在内存中是否存在。逻辑地址空间可能很大,也意味着有可能有一部分的逻辑地址空间可能没有对应到物理空间,这时候它的存在属性就应该不存在了,若存在属性 1代表存在,0 代表不存在,可能是0,它不存在。当然还有其他属性,比如说代表这个页读或者写的情况,写过、读过还是没有读、没有写等等,这些属性都是有一定的表示。

2. 地址转换的例子

首先看看内存空间的大小,首先是逻辑地址空间,逻辑空间一共有16 bit, 意味着它有64K 的地址空间,但是物理地址空间只有32 KB,可看出来逻辑地址空间和物理地址空间是不一致的,它们之间不对等,但是每一个业内的偏移是一样的,因为每一页的大小是一样的,页大小和页帧大小 都是1K ,1024B。

在这种情况下,逻辑页的两个地址,(4,0)(3,1023)代表什么意思?(4,0)就是说逻辑页号是4,页内偏移是0。(3,1023)是逻辑页号是3,页内偏移是1023,这种情况下它对应的物理页地址是多少?

  • 首先 CPU 要找这个地址,先看第一个(4,0),代表页号是4,查页表,第四项有标志位和相应帧号,帧号看是0,但是需要注意它的标志位这个红色的那个0什么意思呢?就是代表当前物理页帧是否存在?如果0代表不存在,1代表存在,这里面标识的是0,这个页对应的物理页页帧在内存中不存在,没有映射关系,所以说如果 CPU 访问这个地址,它应该产生异常,就是内存访问异常。
  • 看第二个(3,1023),页号是3,业内偏移是1023。页号3表示第四项,页表里面第四项的驻留位就是存在位是1,代表页号对应的物理叶帧确实在物理内存中存在。对应的页帧号是多少?可以看看那里面查出来的二进制是00100,也就是它的页帧号是4,可以映射出它的页帧对应的物理页帧号是4,页帧内的偏移和页的偏移是一样的,偏移是1023,那就形成了物理页帧的地址,它的页帧号是4,页帧内的偏移是1023,运算出来可以看到,指向了物理空间种(4,1023)这个位置。

这就是整个映射过程,可以看到页表项里面也会出现两种情况:

  1. 一种情况是说物理页帧存在,可以找到对应的映射地址。还有一种情况是物理页帧不存在,又会产生内存访问异常。一旦出现异常之后,操作系统来做进一步处理,一般情况下,如果是因为非法访问,就直接把进程给杀死。
  2. 那另一方面,页表在使能页机制之前,页表要建立好,页表建立过程是操作系统来完成。这是页表访问的例子。

3.分页机制的性能问题

看起来好像这个机制也是比较完善的,可以完成从逻辑地址到物理地址转换,那有没有问题?其实这里面主要存在的问题就是空间代价问题,第二个时间开销问题。

如果说直接看刚才那幅图没有任何问题,如果要在计算机系统里面把这个机制给实现起来,需要考虑这两个问题,希望空间占用得越小越好,希望执行的速度越快越好。这两个问题是不是都可以很好地解决呢?

举个例子,比如说现在计算机寻址系统越来越大,现在用到的计算机很多是64 位计算机,也意味着它寻址空间是 2 64 2^{64} 264,如果说这里一个页的大小只有1024,也就说1K,这么大一个寻址空间,要建多大的页表才能够把这个映射关系表示完呢?答案是 2 54 2^{54} 254次方。这是多大的page table 项?其实容量是相当大。

  • 根据上述例子,现在一般计算机没有这么大的空间,完全无法存下一个页表,那也就没法去完成这个对应关系,第一个问题就出来, 这个页表有可能由于逻辑地址空间很大,导致对应的页表也很大, 这是一个。第二个在计算机系统里面,可以跑多个应用程序,有多个应用程序都在内存中,而为了有效地实现地址空间隔离,其实需要每一个运行的程序都有自己的一个页表。那如果有 n 个程序,对应有 n 页表,那也意味着页表所占空间要 n 份,这其实也很耗空间,第一个问题就是页表可能会导致占的空间很大。

  • 第二个访问效率问题,既然页表空间很大,那很明显整个页表组织结构不能放在 CPU 里面,因为 CPU 空间很小,CPU 里面有 cache ,最多几兆,但是现在这个页表按照刚才那种设计,相当大 ,CPU 放不下,那就需要把页表放内存里面。如果页表放到内存里面,每一次寻址访问一个内存,就要访问一次页表,这个页表本身也在内存里面,那意味着要去做一次内存寻址,要访问两次内存,那这个开销也是很大的。

所以说这两个问题就需要去想出一些对策,来有效地解决或者缓解时间和空间上的问题。那么对于计算机系统而言,一般来说解决时间空间问题有两种办法:

  • 一种办法是缓存,希望把一些最常用的数据或者最常用的内容缓存到离 CPU 很近的地方。就像前面讲到内存管理系统中 cache 一样,把最常的东西放 cache 里面,可以提升访问速度。
  • 第二个通过一种间接的方式,通过间接方式可以把一个很大的空间拆成比较小的空间,叫间接方式,后面可以看到,通过多级页表机制可以有效地缓解页表占用空间过大的一个问题。

4. Translation Look-aside Buffer (TLB)

通过两种方法来解决页表空间和时间问题,首先讲时间,这个时间叫 TLB,就是在 CPU 里面的 MMU(MMU 是内存管理单元),内存管理单元里面有一个叫做 TLB(translation look-aside Buffer),这是一个缓存,缓存页表里的内容。

上图可以看到 TLB 是一个特殊的一块区域,位于CPU 内部。里面包含两项,一个 p 值,一个 f 值,p 值是 key,f 是 value,key 和 value 就形成 TLB 表项,而 TLB 表项本身是用相关存储器来实现,相关存储器是快速查询的存储器,它的速度很快,可以并发地进行查找,但是实现的代价,容量都是有限的,实现代价很大,所以容量是有限的,只有有限的个数,那么可以把当前经常用到的页表项放到 TLB 里面去,这样就可以提升访问速度,这时候就不需要查页表了,当 CPU 得到一个逻辑地址的时候,首先根据这个 p 去查这个 TLB,如果 TLB 里面存在这个 p 这个 key 的话,那么很容易给得到这个 f,因为它们保存在一个TLB 项里面,那么有了 f 之后,加上 offset, 就可以直接得到物理地址,就可以去找内存中对应这个地址的内容,那就避免了一次页表访问。

如果出现 TLB 访问不到的情况,那么CPU 会去查页表,因为 TLB 表项里面已经不存在了,那不得不查页表,在页表里面应该有对应的那么一项,如果这一项里面存在位值是1的话,那么就会把这一项里面的 frame number 号取回来,取到 TLB 里面,用 TLB 表项来存储缓存这个值。那么可以看到,最常用的一些访问会放在 TLB 表项里面,不常用的就没有了,那这时候可以使得 TLB 的访问效率很高。

会不会 TLB 出现缺失情况会很大呢?

TLB 缺失不会很大,为什么那么说,因为一个页,一般来说现在32位系统里面一个页是4K,那么要访问4K 次,如果每一个地址都要访问的话,这访问4K 次才会引起一次TLB的缺失,这个其实还是可以接受的程度。就是说通过某种机制可以使得TLB的缺失尽量小,那这个机制什么呢?写程序的时候需要注意,尽量写出程序有一定的局部性,访问的局部性,把平时的这些访问集中在一个区域里面,这样可以有效地减少 TLB 的缺失,这当然是编程的时候需要注意的问题。 通过这种方式使得可以尽量地避免对内存页表访问,从而可以使得整个寻址的开销得到极大降低。

  • 另外还需要注意,TLB 缺失之后,要从页表里把这项取出来,再存到 CPU 里面去,那这个过程是由操作系统软件来做,还是 CPU 硬件直接就做完了?

    这跟 CPU 本身的特征有关系的,如果现在是X86 CPU, TLB MISS 之后从页表中取对应项到 TLB 中去的这个过程,完全硬件来完成,不需要操作系统参与,这是一种情况。但是对于另一类 CPU,比如说 Linux,那么它这个过程是由操作系统来完成,这是由软件来实现的,这两种情况都存在。

相关推荐
无为之士20 分钟前
Linux自动备份Mysql数据库
linux·数据库·mysql
岑梓铭37 分钟前
(CentOs系统虚拟机)Standalone模式下安装部署“基于Python编写”的Spark框架
linux·python·spark·centos
努力学习的小廉37 分钟前
深入了解Linux —— make和makefile自动化构建工具
linux·服务器·自动化
MZWeiei41 分钟前
Zookeeper基本命令解析
大数据·linux·运维·服务器·zookeeper
7yewh1 小时前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
小张认为的测试1 小时前
Linux性能监控命令_nmon 安装与使用以及生成分析Excel图表
linux·服务器·测试工具·自动化·php·excel·压力测试
打鱼又晒网1 小时前
linux网络套接字 | 深度解析守护进程 | 实现tcp服务守护进程化
linux·网络协议·计算机网络·tcp
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网
蜜獾云2 小时前
docker 安装雷池WAF防火墙 守护Web服务器
linux·运维·服务器·网络·网络安全·docker·容器
小屁不止是运维2 小时前
麒麟操作系统服务架构保姆级教程(五)NGINX中间件详解
linux·运维·服务器·nginx·中间件·架构