虚拟内存如何翻译出物理地址

在进行详细阐述之前需要了解的前提知识:

1.  内核或者说系统为每一个进程维护一个叫做 任务结构 的数据结构(其实就是一个结构体,另:该任务结构是一个所谓叫做进程表的双向链表的一个成员, 进程表包含系统中打开的每一个进程),结构体名为 task_struct,其中内部有一个结构体指针叫做 mm ,可以在下面的代码中找到这么一行 struct mm_struct *mm; mm指向一个结构体 mm_struct(同样的作者也将该结构体一并贴出到下面的代码中),mm_struct中又有一个指针变量 pgd, 是Page Global Directory的缩写,指向页全局目录的基础地址。作者猜想:每当切换到某个进程时,便会索引出对应进程任务结构中的mm_struct,然后获取出pgd内容,将它写进CR3,CR3是存储页表基址的寄存器,叫做PTBR,全称Page Table Base Register. task_struct内部结构如下图1.1所示:

图1.1 task_struct 内部结构

2. 虚拟地址由两部分组成,VPN+VPO,即 Virtual Page Number 和 Virtual Page Offset 的缩写,叫做虚拟页号和虚拟页偏移量。MMU翻译虚拟地址的过程如下图1.2所示:

图1.2 MMU翻译虚拟地址为物理地址的过程

详细过程如下:

当进程访问某个虚拟地址时,MMU的硬件翻译单元便会开始进行地址翻译,翻译过程如下:

根据虚拟地址中虚拟页号到PTBR指向的页表中索引出页表条目,页表条目中包含有两个字段:有效位+物理页号,有效位指示当前页是否存在在物理页中,如果不存在则产生缺页异常,由缺页异常处理程序进行页面调度(物理页在磁盘和主存之间进行传送页的活动),并更新页表条目,然后重新索引到该页表条目,由于页表已经更新并指示当前物理页号字段不为空,将不会再次产生缺页异常,那么MMU可以继续工作,根据对应页表条目中的物理页字段,索引到物理页,再结合虚拟地址的虚拟页偏移量VPO,算出最后的物理地址。

 

以下是 struct task_struct 以及 struct mm_struct 的内容,分别来自作者系统目录:

/usr/lib/modules/5.6.6-arch1-1/build/include/linux/sched.h

/usr/lib/modules/5.6.6-arch1-1/build/include/linux/mm_types.h