Linux 虚拟地址到物理地址转换
Table of Contents
概念
虚拟地址和物理地址的概念
CPU通过地址来访问内存中的单元,地址有虚拟地址和物理地址之分,如果CPU没有MMU(Memory Management Unit,内存管理单元),或者有MMU但没有启用,CPU核在取指令或访问内存时发出的地址将直接传到CPU芯片的外部地址引脚上,直接被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为物理地址(Physical Address,以下简称PA),如下图所示。
物理地址示意图
如果CPU启用了MMU,CPU核发出的地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将虚拟地址映射成物理地址,如下图所示。
虚拟地址示意图
虚拟内存地址和物理内存地址的分离,给进程带来便利性和安全性。虚拟地址必须和物理地址建立一一对应的关系,才可以正确的进行地址转换。
记录对应关系最简单的办法,就是把对应关系记录在一张表中。为了让翻译速度足够地快,这个表必须加载在内存中。不过,这种记录方式惊人地浪费。
因此,Linux采用了分页(paging)的方式来记录对应关系。所谓的分页,就是以更大尺寸的单位页(page)来管理内存。在Linux中,通常每页大小为4KB。如果想要获取当前树莓派的内存页大小,可以使用命令:
baiheng@baiheng-OptiPlex-5055-Ryzen-CPU:~$ getconf PAGE_SIZE
4096
地址转换过程
32bit 分页机制下虚拟地址是由32bit组成的,常规4KB分页,32位的虚拟地址被分成3个域。
Directory(目录) | Table(页表) | Offset(偏移) |
最高10位 | 中间10位 | 最低12位 |
具体的地址转换过程,文字描述太累,看图直观一些:
依据以下步骤进行转换:
- 从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
- 根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
- 根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
- 将页的起始地址与线性地址中最后12位相加,得到最终我们想要的葫芦;
这个转换过程,应该说还是非常简单地。
前面说了二级页管理架构,不过有些CPU,还有三级,甚至四级架构,Linux为了在更高层次提供抽像,为每个CPU提供统一的界面。提供了一个四层页管理架构,来兼容这些二级、三级、四级管理架构的CPU。这四级分别为:
- 页全局目录PGD(对应刚才的页目录)
- 页上级目录PUD(新引进的)
- 页中间目录PMD(也就新引进的)
- 页表PT(对应刚才的页表)。
整个转换依据硬件转换原理,只是多了二次数组的索引罢了,如下图:
更多推荐
所有评论(0)