MMU工作原理
MMU
基础概念
虚拟/物理内存
对于提供了MMU功能的处理器而言,假设进程所能访问到的地址空间是4GB;则这4GB的空间可被划分为两个部分:
-
用户空间
0GB~3GB
PAGE_OFFSET,x86中的值是0xC0000000)
-
内核空间
3GB~4GB
。内核空间又可划分出物理/虚拟内存
-
物理内存映射区
3GB~3GB+vmalloc_start
之间的区域作为物理内存映射区使用- 包含了内核镜像、物理页框表mem_map等等
-
虚拟内存vmalloc区域,在物理内存映射区域之后:
-
vmalloc_start
-
位置在**
3GB+160MB
位置附近**(在物理内存映射区与vmalloc_start位置之间还存在一个8M的gap来防止越界)。
-
-
vmalloc_end
- 位置在接近4GB的位置
- (系统会在最后的位置处保留一片128KB大小的区域专用于页面映射)
-
-
MMU
虚拟地址概念的处理器才有MMU —— CPU
两个步骤
- CPU访问的虚拟地址转换成物理地址
- 通过物理地址在cache、主存或者EMMC中获取相应的数据。
MMU是Memory Management Unit的缩写,内存管理]单元。
它是一种负责处理 中央处理器(CPU)的内存访问请求的计算机硬件。
它的功能包括
-
虚拟地址到物理地址的转换(即虚拟内存管理)
-
提供硬件机制的内存
内存保护、中央处理器高速缓存 的控制,
在较为简单的计算机体系结构中,负责 总线的仲裁 以及存储体切换(bank switching,尤其是在8位的系统上)
DMA
DMA是用来传输数据的,全称Direct Memory Access,即直接存储器(内存)访问。
提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 在传输数据时,无需占用CPU的外设。
DMA传输方向有三个:
- 外设到内存。即从外设读取数据到内存。例如ADC采集数据到内存,ADC寄存器地址为源地址,内存地址为目标地址。
- 内存到外设。即从内存读取数据到外设。例如串口向电脑发送数据,内存地址为源地址,串口数据寄存器地址为目标地址。此时内存存储了需要发送的变量数据。
- 内存到内存。以内部flash向内部sram传输数据为例,此时内部flash地址即为源地址,内部sram地址即为目标地址。同时,需要将DMA_CCRx寄存器的MEM2MEM置位。
名词介绍
虚拟地址相关
- 虚拟内存(Virtual Memory,VM):为每个进程提供了一致的、连续的、私有的内存空间,简化了内存管理。
- 虚拟地址空间 (Virtual Address Space,VAS):每个进程独有。
- 虚拟页(Virtual Page,VP):把虚拟内存按照页表大小进行划分。
- 虚拟地址(Virtual Address,VA):处理器看到的地址。
- 虚拟页号(Virtual Page Number,VPN):用于定位页表的PTE。
物理地址相关
- 物理内存(Physical Memory,PM):主存上能够使用的物理空间。
- 物理页(Physical Page):把物理内存按照页表的大小进行划分。
- 物理地址(Physical Address,PA):物理内存划分很多块,通过物理内存进行定位。
- 物理页号(Physical Page Number,PPN):定位物理内存中块的位置。
- 主存
- 将主存看成是一个存储在磁盘上的地址空间的高速缓存
- 当运行多个进程或者一个进程需要更多的空间时,主存会不够用,需要更大、更便宜的磁盘保存一部分数据。
页表相关
- 页表(Page Table):虚拟地址与物理地址之间的 映射表的集合。
- 维护,由操作系统实现
- 存放,在物理内存(主存)中
- 查询,由 MMU的TWU模块是实现
- 页表条目(Page Table Entry,PTE):虚拟地址与独立地址具体对应的记录。
- 页全局目录(Page Global Directory,PGD):多级页表中的最高一级。
- 页上级目录(Page Upper Directory,PUD):多级页表中的次高一级。
- 页中间目录(Page Middle Directory,PMD):多级页表中的一级。
历史
将整个程序加载到物理内存中:静态分区、动态分区、虚拟内存
静态/动态分区
为支持多个程序的并行——静态分区
- 在编译阶段将不同程序,分别划分出对应的内存区域上
- 存在问题
- 内存分区大小与程序大小要匹配
- 地址空间无法动态的增长
于是诞生了,动态分区
- 内存上线划出一块区域给操作系统
- 剩余的内存空间给用户进程使用,用户程序所使用的内存空间,跟随程序大小及数目进行变动。
静态分区、动态分区,都存在的问题:
- 进程地址空间安全问题
- 内存使用效率低。
分页机制
早期的内存&程序都是比较小的,程序直接加载到内存中运行。
后来程序的大小变得很大不能将整个程序加载到物理内存中
- 物理内存没有这么大
- 如果将整个程序加载到内存,为了多程序并行,就需要将大量的数据及代码换入、换出,这导致程序运行效率低下。
好在程序运行遵循时间、空间局部性原理,进而出现了分页机制。
分页机制 从根本上解决了高效使用物理内存的问题
-
每次只需要将几页的代码、数据从磁盘中加载到内存,程序就能正常运行。
-
程序运行过程中,需要新的代码、数据会产生缺页异常
对应的代码、数据会从磁盘加载到内存,然后程序从异常恢复正常运行。
虚拟内存
虚拟内存:让多程序安全、高效地并行运行
物理内存中存放多个程序的代码及数据
- 让每个程序认为自己是独自、连续的使用内存
- 每个程序之间的内存形成了安全隔离,避免程序破坏彼此的内存。
虚拟内存及分页机制的出现,解决了进程地址空间安全性的问题和内存使用效率低的问题。
但由于本来CPU可以直接通过访存执行程序,现在引入了虚拟地址到物理地址的转换,这带来了新的开销。存在系统性能问题。
MMU
MMU的意义
在没有MMU的年代,对于支持虚拟内存、分页机制的系统,需要CPU寻址虚拟地址。
为了避免这一开销,现在虚拟地址不会直接发给内存控制器,而是先发给 硬件模块 —— 内存管理单元(Memory Manager Unit,MMU)。
- 负责将虚拟地址转换和翻译成物理地址的一个硬件模块
- 提升虚拟地址到物理地址转换的速度,减少转换所消耗的时间。
因此,哪怕运行内存有限,也可以通过动态分区、分页机制、虚拟内存、MMY单元,并行运行特别多的程序。
MMU的组成
MMU包含两个模块
- TLB(Translation Lookaside Buffer)
- 一个高速缓存,用于缓存虚拟地址到物理地址(页表转换)的转换结果。
- 缩短页表转换的查询所用时间
- TWU(Table Walk Unit)
- 页表查询的过程由TWU硬件完成
- TWU页表遍历模块,完成页表的遍历查询,减少对CPU资源的消耗。
框架
总览
页表的查询是一个耗时的过程
页表(Page Table):虚拟地址与物理地址之间的 映射表的集合。
- 维护,由操作系统实现
- 存放,在物理内存(主存)中
- 查询,由 MMU的TWU模块是实现
-
得到物理地址
-
TLB命中(理想情况)。TLB直接得到虚拟地址对应的物理地址。
-
TLB未命中。MMU通过TWU查询页表,翻译虚拟地址得到物理地址。
-
-
查询物理地址,并返回给CPU
查询是否缓存命中——物理地址的内容是否存在于cache中
-
缓存命中
- 直接取出物理地址对应的内容返回给处理器。
-
未缓存命中 —— 尝试在主存(页表)获取对应物理地址的内容
-
获取到(页命中)
- 回写到cache返回给处理器。
-
没获取到(缺页异常)
- 触发与MMU相关的缺页异常
- 异常处理过程中
- 将DMA(例如EMMC)中相关的数据加载到主存,主存建立相应的页表
- TLB中建立映射
- 将物理地址对应的内容返回给cache及处理器。
-
-
页命中、缺页
页命中
- 处理器要对虚拟地址VA进行访问。
- MMU的TLB没有命中,通过TWU遍历主存页表中的PTEA(PTE地址)。
- 主存向MMU返回PTE。
- MMU通过PE映射物理地址,并把它传给高速缓存或主存。
- 高速缓存或主存返回物理地址对应的数据给处理器。
缺页
- 处理器要对虚拟地址VA进行访问。
- MMU的TLB没有命中,通过TWU遍历主存页表中的PTEA(PTE地址)。
- 主存向MMU返回PTE。
- PTE中有效位是0,MMU触发一次异常,CPU相应缺页异常,运行相应的处理程序。
- 缺页异常处理程序 选出物理内存中的牺牲页,若这个页面已经被修改,将其换出到EMMC。
- 缺页异常处理程序从EMMC中加载新的页面,并更新内存中页表的PTE。
- 缺页异常处理程序返回到原来的进程,再次执行导致缺页的指令。CPU将引起缺页异常的虚拟地址重新发给MMU。由于虚拟页面现在缓存在主存中,主存会将所请求的地址对应的内容返回给cache和处理器。
多级页表映射过程
物理页面大小一级地址总线宽度不同,页表的级数也不同。以AArch64运行状态,4KB大小物理页面,48位地址宽度为例,页表映射的查询过程如图:
对于多任务操作系统,每个用户进程都拥有独立的进程地址空间,也有相应的页表负责虚拟地址到物理地址之间的转换。MMU查询的过程中,用户进程的一级页表的基址存放在TTBR0。操作系统的内核空间公用一块地址空间,MMU查询的过程中,内核空间的一级页表基址存放在TTBR1。
当TLB未命中时,处理器查询页表的过程如下:
- 处理器根据虚拟地址第63位,来选择使用TTBR0或者TTBR1。当VA[63]为0时,选择TTBR0,TTBR中存放着L0页表的基址。
- 处理器以VA[47:39]作为L0的索引,在L0页表中查找页表项,L0页表有512个页表项。
- L0页表的页表项中存放着L1页表的物理基址。处理器以VA[38:30]作为L1索引,在L1页表中找到相应的页表项,L1页表中有512个页表项。
- L1页表的页表项中存放着L2页表的物理基址。处理器以VA[29:21]作为L2索引,在L2页表中找到相应的页表项,L2页表中有512个页表项。
- L2页表的页表项中存放着L3页表的物理基址。处理器以VA[20:12]作为L1索引,在L3页表中找到相应的页表项,L3页表中有512个页表项。
- L3页表的页表项里,存放着4KB页面的物理基址,然后加上VA[11:0],这样就构成了物理地址,至此处理器完成了一次虚拟地址到物理地址的查询与翻译的工作。