内核空间的虚拟内存地址
页表与MMU
- 虚拟地址空间和物理地址空间都分成同等大小的块,也称为页,按照虚拟页和物理页进行转换。
- 根据软件配置不同,这个页的大小可以设置为 4KB、2MB、4MB、1GB,这样就进入了现代内存管理模式——分页模型。
- 在4GB,32位操作系统,页面大小为4KB
- 一个虚拟页可以对应到一个物理页,由于页大小一经配置就是固定的,所以在地址关系转换表中,只要存放虚拟页地址对应的物理页地址就行了。
三级页表到四级页表
2.6.11版本开始,采用四级分页模型
- 三级页表:PGD、PMD、PTE、page offset
- 四级页表:
- 页全局目录(Page Global Directory)
- 页上级目录(Page Upper Directory)
- 页中间目录(Page Middle Directory)
- PTE (Page Table Entry)
- page offset
- 对于没有启用物理地址扩展的32位系统,Linux取消了页上级目录和页中间目录,仅使用了两级页表。
- 启用了物理地址扩展的32位系统,Linux取消了上级目录,使用三级页表。
- 对于64位系统,Linux根据硬件对线性地址位的划分来决定采用三级或者四级页表。
MMU
- MMU 即内存管理单元,是用硬件电路逻辑实现的一个地址转换器件,它负责接受虚拟地址和地址关系转换表(页表基址寄存器),以及输出物理地址。
- 根据实现方式的不同,MMU 可以是独立的芯片,也可以是集成在其它芯片内部的,比如集成在 CPU 内部,x86、ARM 系列的 CPU 就是将 MMU 集成在 CPU 核心中的。
- MMU有不同模式,可以处理不同分段的下的虚拟地址?
- 由于保护模式的内存模型是分段模型,它并不适合于 MMU 的分页模型,所以我们要使用保护模式的平坦模式,这样就绕过了分段模型。
- 保护模式下的分页 3级页表
- 页目录索引(10)、页表索引(10)、页内偏移(12),
- 只有一级页目录,其中包含 1024 个条目(2^10) ,每个条目指向一个页表,每个页表中有 1024 个条目 (2^10)。
- 其中一个条目就指向一个物理页,每个物理页 4KB。
- 长模式下的分页 4级页表
- 64 位虚拟地址被分为 6 个位段,分别是:保留位段,顶级页目录索引(8)、页目录指针索引(8)、页目录索引(8)、页表索引(8)、页内偏移(12),
- 顶级页目录、页目录指针、页目录、页表各占有 4KB 大小,其中各有 512 个条目,每个条目 8 字节 64 位大小
页表
地址关系转换表,其实它有个更加专业的名字——页表。它描述了虚拟地址到物理地址的转换关系,也可以说是虚拟页到物理页的映射关系,所以称为页表。
- MMU工作流程
- 一个虚拟地址被分成从左至右四个位段。
- 第一个位段索引顶级页目录中一个项,该项指向一个中级页目录
- 然后用第二个位段去索引中级页目录中的一个项,该项指向一个页目录
- 再用第三个位段去索引页目录中的项,该项指向一个物理页地址
- 最后用第四个位段作该物理页内的偏移去访问物理内存(32为系统,页大小4KB,2^12,需要12位)。
相同虚拟地址如何不混淆?
- 由于每个进程都有自己独立的地址空间,所以,如果系统采用一级列表,那么每个进程都需要额外4MB的内存,来存储完整的页表项
- 如果是32位的系统,1个页大小4KB,假设一个页表项的大小是4B,那么需要1M个页(4KB * 1M = 4GB),所有页表项的大小就是4MB
- 从高位到低位:10位存页目录号+10位存页号+12位存偏移地址(2^12=)
- 如果采用二级列表,一个进程额外需要4KB的页目录表,12KB的页表项
- 同样,1个页4KB,将1M个页表项划分成1K份,每份有1K个页表项,构建一个二级页表目录,每个页表目录项就对应着1K个页表项,假设一个页表项和一个页目录项的大小都是4B对于一个进程来说,在运行时,页目录表肯定是常驻内存的,大小为1K 4B = 4KB,而页表项则是按需装入即可,默认程序是4MB代码+4MB数据+4MB栈,那么就对应了1K + 1K + 1K = 3K个页才能把这些数据容纳(3K 4KB = 3 * 4MB),一个页表项4B,那么3K个页表项就是12KB。
###