分页内存简述¶
在 lab 1 中,由于面向 x64 的 UEFI 已经开启了分页机制,所以这里会将一部分概念提前介绍。
页表¶
页表是操作系统中常用的内存模型,利用它可以实现虚拟内存、进行内存隔离、避免内存碎片等。作为操作系统内存管理的核心,在现代化的 OS 开发中,页表的参与是必不可少的。
在操作系统课程中,有关页表的内容往往被放置在后面的章节中,但是为了面向现代化的实验内容,这里需要大家对页表是什么、能做什么、为什么需要三个问题有一个初步的了解。
在计算机组成原理课程中,已经有过对于页表的介绍,它是一个虚拟地址到物理地址的映射表,通过它可以实现虚拟内存。
然而于这门课程所介绍的有所不同,在 x64 架构中,页表不再是一个简单连续的映射表,而是一个树状结构,这样的结构被称作多级页表。在本实验的实现中,会使用到四级页表(PML4)。
每一级的页表索引号都可以通过虚拟地址推导出来,对于一个 64 位的虚拟地址:
64 | 48 | 39 | 30 | 21 | 12 | 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
L4 Index | L3 Index | L2 Index | L1 Index | Page Offset |
为了降低学习难度和实现的负担,本实验中将直接使用 x86_64 crate 中所提供的 PageTable
结构体和 Cr3
寄存器的封装。
具体的寻址过程可以参考 地址转换范例 中的描述。
页表表项¶
页表中的每一个表项都是一个 64 位的数据,能够描述一个页表项的属性,及一些权限管理:
- Readable:是否可读,表示是否允许从这个页读取数据。
- Writable:是否可写,表示是否允许向这个页写入数据。
- Executable:是否可执行,表示是否允许执行这个页上的指令。
这三个主要权限一般被简写为 R/W/X,这部分内容将在处理 ELF 文件时用到。
它的具体结构可以参考 页表格式 中的描述。
虚拟内存¶
通过利用页表,操作系统可以实现虚拟内存,将一部分分配出的物理内存映射到虚拟地址空间中。
利用这种方式,操作系统可以限制用户进程的内存访问权限,实现内存隔离,同时也可以避免内存碎片的产生:对于用户程序所看到的虚拟地址空间,它是连续的,但是对于操作系统来说,它可以将这些虚拟地址映射到任意的物理地址上,因此可以随用随取,按需分配。
x64 相关寄存器¶
在 x64 架构中,有一些特殊的寄存器与页表相关,且在本实验中会用到,它们分别是:
- CR0:控制寄存器,存储了一些控制系统运行状态的标志位,包括根页表的写保护位。
- CR2:页错误地址寄存器,存储了最近一次页错误的虚拟地址。
- CR3:页表根地址寄存器,存储了页表的物理地址,也就是 PML4 的地址。
参考资料¶
以下的资料提供了更加详细的页表介绍,作为这里简略介绍的补充,建议大家尝试进行阅读。