Linux 虚拟地址到物理地址的转换

概念:
虚拟地址和物理地址的概念 
    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

地址转换过程

具体的地址转换过程,文字描述太累,看图直观一些:

依据以下步骤进行转换:

  1. 从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
  2. 根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
  3. 根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
  4. 将页的起始地址与线性地址中最后12位相加,得到最终我们想要的葫芦;

这个转换过程,应该说还是非常简单地。

前面说了二级页管理架构,不过有些CPU,还有三级,甚至四级架构,Linux为了在更高层次提供抽像,为每个CPU提供统一的界面。提供了一个四层页管理架构,来兼容这些二级、三级、四级管理架构的CPU。这四级分别为:

  • 页全局目录PGD(对应刚才的页目录)
  • 页上级目录PUD(新引进的)
  • 页中间目录PMD(也就新引进的)
  • 页表PT(对应刚才的页表)

整个转换依据硬件转换原理,只是多了二次数组的索引罢了,如下图:

另外参考阅读:https://blog.csdn.net/yunfenglw/article/details/45603823 

发布了140 篇原创文章 · 获赞 65 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/paradox_1_0/article/details/103374520