在之前的文章中,我们介绍过 GDT(全局描述符表)以及一致代码段和非一致代码段,这篇文章我们再回到描述符,这次我们来以 ARM 架构为例了解一下页表描述符。
在这篇文章中,我们会看到以下内容:
页表是什么?
一级页表的地址变换过程
由一级描述符来获取二级描述符或者段地址的过程
页表
页表是什么?
页表是一种特殊的数据结构,放在系统空间的页表区,存放逻辑页与物理页帧的对应关系。 每一个进程都拥有一个自己的页表,PCB表中有指针指向页表。
(来自百度百科)
通俗的来讲,页表的内容就是一个描述符(关于描述符的介绍请参看该系列文章中的《实现一个 GDT》),我们可以将 GDT 理解成为一个一级描述符表,将 LDT 理解为一个二级描述符表。这篇文章我将以 ARM 体系结构为例,介绍一级页表的地址变换过程以及根据一级页表的类型来获取二级描述符表或者段的物理地址。
MMU 中的地址变换
ARM 系统中的虚拟空间到物理存储空间的映射是以内存块为单位进行的,即虚拟内存中的一块连续的空间被映射到物理存储空间一段连续的地址空间。
ARM 支持以下几种大小的存储块:
- 段(Section):大小为1MB
- 大页(Large Pages):大小为64KB
- 小页(Small Pages):大小为4KB
- 微页(Tiny Pages):大小为1KB
在页表中,每一个地址变换条目实际上记录了一个虚拟空间的存储块的基地址与物理空间存储块的对应关系,根据存储块的大小,会有多种不同的地址变换。
在 ARM 中,MMU 实现虚拟地址到物理地址的映射是通过两级页表来实现的(以段为单位的地址变换是通过一级页表实现的)
ARM 中与 MMU操作相关的寄存器
寄存器 | 作用 |
---|---|
C1 | 配置 MMU 中的一些操作 |
C2 | 保存页表的基地址 |
C3 | 设置域的访问控制属性 |
C4 | 保留 |
C5 | 内存访问失效状态指示 |
C6 | 内存访问失效时失效的地址 |
C8 | 控制与清除 TLB 内容相关操作 |
C10 | 控制与锁定 TLB 内容相关操作 |
#一级页表
如何获得一级页表的地址?
从上表中我们可以看到 C2中保存了页表的基地址,由此,我们可以看到下图:
一级页表地址 = C2寄存器的高18位 + 虚拟地址的高22位 + 00 (共32位)
一级描述符
我们得到了一级页表的地址,对应地址空间的内容就是一级描述符。
一级描述符分为以下类型:
- 粗粒度页表描述符
- 段描述符
- 细粒度页表描述符
从以上三幅图中我们可以看到,不同类型的描述符是由描述符的最低2位决定的,分别为:
类型 | 低1位 | 低0位 |
---|---|---|
粗粒度页表描述符 | 0 | 1 |
段描述符 | 1 | 0 |
细粒度页表描述符 | 1 | 1 |
无效 | 0 | 0 |
获得二级描述符表或者段地址过程
由粗粒度页表描述符获得二级描述符表
从图中我们可以清楚的看到由粗粒度描述符表得到二级描述符表地址的过程:
二级描述符表地址 = 粗粒度描述符表高22位 + 虚拟地址[19:12]位 + 00 (共32位)
由细粒度页表描述符获得二级描述符表
从图中我们可以清楚的看到由细粒度描述符表得到二级描述符表地址的过程:
二级描述符表地址 = 粗粒度描述符表高20位 + 虚拟地址[19:10]位 + 00 (共32位)
由段描述符表描述符获得段的物理地址
从图中我们可以清楚的看到由段描述符表描述符获得段的物理地址的过程:
段物理地址 = 段描述符高12位 + 虚拟地址低20位
#总结
在这篇文章中,我们加深了之前对描述符的理解,同时对描述符的作用做了更直接的解释,对于页表也进行了介绍。这篇文章中我们以 ARM 体系结构为例讲解了二级页表的工作,其实,按照同样的道理我们也可以设计出三级页表以及更多级的页表。
本文的版权归作者 罗远航 所有,采用 Attribution-NonCommercial 3.0 License。任何人可以进行转载、分享,但不可在未经允许的情况下用于商业用途;转载请注明出处。感谢配合!