目录V 1.0 2024年5月7日 发布于博客园
MMU概述
MMU即内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU),它对处理器发出的访存地址进行映射和检查,可以让处理器发出的访存地址去访问不同的物理内存单元。
它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线的仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。
例如,处理器发出的地址是0,通过MMU后则访问的可能是以4096为物理地址的内存单元。同时它还检查这个地址是不是存在以及有没有访问权限。例如,我们可以通过对MMU的设置,让应用软件不能访问操作系统内核的存储空间。
MMU关闭时
在没有MMU或者MMU关闭状态下,内核发出的地址,直接被送到总线上作为物理地址去访问内存。有很多简单的硬件系统确实和上图一样没有MMU,或者有个比MMU更简单的器件叫MPU即内存保护单元,没有MMU的地址映射功能。
MMU打开时
上图是启用MMU的简易图。处理器的内核发出的地址,首先要通过这个黑盒子才能被送到总线上去访问内存。当处理器的内核发出的地址到达MMU时,MMU首先检查这个地址是否能被访问,然后用一套机制对这个地址进行转换,生成一个新的地址,最后把这个新生成的地址放到总线上去访问内存。人们对这两种地址用了两个专业的术语,从处理器内核到MMU的地址,叫虚拟地址,它还有一种地址。把MMU放到总线上的地址称为物理地址。
MMU页表
MMU把虚拟地址转换成对应的物理地址,需要一些转换规则,实现这一转换规则的东西,实际上有个专业的术语叫页表。
页表是存在于内存中的一块数据,这块数据中有很多条目,在ARM920T的MMU下,每个条目是一个存储字大小即32位。相当一个整形数组,用C语言可以这样描述:int pagetbl[xxxx]。具体有多少条目要视情况而定。如图3-37所示,这些条目的位段,有一定的格式。根据这些条目中不同的数据,MMU转换后的物理地址和地址空间块即页面的大小也会有所不同。
页表中的每个条目表示一个地址转换规则。MMU地址映射时是按照地址空间块映射的,即一块连续的虚拟地址空间对应一块连续的物理地址空间。这个地址空间块叫“页面”
当然图3-36中的地址空间块的大小是可变的。ARM920T处理器中的MMU支持4种不同大小的地址空间块,分别如下:
·1MB,称为段;
·64KB,称为大页;
·4KB,称为小页;
·1KB,称为极小页。
段
段映射下,ARM920T的MMU把虚拟地址空间和物理地址空间分成1MB大小的地址空间块,即每个页面大小为1MB。由于是1MB大小的页面,所以只需要一级页表。这个页表中有4096个条目。每个条目映射1MB大小的空间,正好对应于ARM920T 4GB的虚拟地址空间。段映射下的页表条目格式如图3-38所示。
大页
大页映射下,ARM920T的MMU把虚拟地址空间和物理地址空间分成64KB大小的地址空间块,即每个页面大小为64KB。由于是64KB大小的页面,所以需要两级页表。一级页表中有4096个条目。每个条目映射二级页表的空间,二级页表中有256个条目。在只有大页的情况下,只用到了前16个条目。每个二级页表的条目可以映射64KB大小的地址空间,大页映射下一级页表条目和二级页表条目的格式如图3-41所示。
小页
小页映射下,ARM920T的MMU把虚拟地址空间和物理地址空间分成4KB大小的地址空间块,即每个页面大小为4KB。由于是4KB大小的页面,所以需要两级页表。一级页表中有4096个条目。每个条目映射二级页表的空间,二级页表中有256个条目,每个二级页表条目可以映射4KB大小的地址空间,小页映射下一级页表条目和二级条目的格式如图3-44所示。
极小页
极小页映射下,ARM920T的MMU把虚拟地址空间和物理地址空间分成1KB大小的地址空间块,即每个页面大小为1KB。由于是1KB大小的页面,所以需要两级页表。一级页表中有4096个条目。每个条目映射二级页表的空间,二级页表中有1024个条目,每个二级页表条目可以映射1KB大小的地址空间。极小页映射下一级页表条目和二级条目的格式如图3-47所示。
在这里,容量计算为:一级页表条目数 * 二级页表条目数 * 每个页面大小=4096 * 1204 * 1 KB = 4096MB = 4GB
为什么要有MMU?
一是内存地址映射;二是内存空间保护。
以一个小程序为例:
MMU把从0开始的虚拟地址空间映射到了从0x1000开始的物理内存空间。当处理器从0地址开始读取程序指令时,实则是读取到是0x1000地址内存单元中的指令。这时我们发现改变MMU的映射规则,就能把程序装载进以任意地址开始的物理内存空间中,只要这个空间可以装载且装得下这个程序就行。
我们假定每个应用程序都是从0地址开始链接的,并且它们拥有4GB的虚拟地址空间。MMU给我们开发软件带来了巨大的方便,而且还能让我们的程序运行得更加稳定、可靠。
操作系统内核只要牢牢地控制每个应用程序的MMU的地址转换规则,并且调度另一个应用程序运行时就让MMU使用另一个应用程序的地址转换规则。操作系统就可以自由地装载应用程序到任意物理内存空间中。应用软件开发商也少了不少麻烦,因为他们始终可以认为他们拥有一个非常大而且连续的内存空间,并且这个内存空间就是他们的,神圣而不可侵犯。
进一步来说,开发MMU的人,还让MMU能够通过具体的地址转换规则判断当前这个地址能不能被转换成物理内存地址去访问内存。如果不能被转换,那么MMU就向CPU发送一个信号,请求CPU来处理这个问题。由此操作系统就能利用这种机制。例如,对内存实施保护,还可以实现这样的机制:只装载应用软件的一部分,当应用程序运行到下一部分时,由于MMU发现地址不能转换,所以向CPU发出地址转换失败的信号,CPU运行操作系统的处理程序:再次装载应用程序的下一部分,并填写好地址转换规则。由于这样,操作系统就可以充分利用有限的物理内存,使之同时运行足够多的应用软件
MMU的关键功能:
-
虚拟内存管理:
- 地址转换:MMU将虚拟地址转换为物理地址。这通常通过页表来完成,页表包含虚拟地址到物理地址的映射。
- 分页:现代操作系统通常使用分页机制管理内存,MMU支持这一机制,允许将内存划分为大小固定的页。
- 页表管理:MMU负责维护页表,并在必要时更新页表条目。
-
内存保护:
- MMU确保进程只能访问它们被允许访问的内存区域。每个页表条目通常包含访问权限信息,如读/写/执行权限。
-
缓存控制:
- MMU可能与CPU缓存(如Translation Lookaside Buffers, TLBs)协作,来加速虚拟地址到物理地址的转换过程。
MMU在C语言编程中的应用:
在C语言编程中,直接与MMU打交道的情况比较少,因为MMU的工作主要是由操作系统内核来管理的。然而,理解MMU的原理对于进行系统编程和性能优化是非常有帮助的。
-
内存分配:
- 通过
malloc
、calloc
、realloc
和free
等函数请求和释放内存时,操作系统可能会用到MMU来分配物理内存并更新页表。
- 通过
-
内存访问:
- 访问通过指针操作的内存时,MMU负责将虚拟地址转换为物理地址。如果程序试图访问未分配的内存或违反了访问权限,MMU可以触发一个异常,通常导致操作系统抛出一个段错误(segmentation fault)。
-
性能优化:
- 理解MMU的工作原理可以帮助程序员编写更高效的代码,例如通过减少页错误(page faults)和提高TLB命中率来优化性能。
-
操作系统级编程:
- 在操作系统级别的编程中,如编写内核模块或操作系统本身,开发者可能需要直接与MMU交互,设置页表项,处理页错误等。
在大多数应用程序开发中,程序员不需要直接处理MMU,因为这些细节被操作系统抽象化了。但是,对MMU的理解对于深入理解计算机系统和解决底层问题是非常重要的。
MMU在ARM系统中
在ARM系统中,4GB的虚拟空间被分成了128个进程空间块,每一个进程空间块大小为32MB。该块中包含一个进程,该进程可以使用的虚拟地址空间为0x000000000x01FFFFFF。这个地址范围也就是CPU看到的一个进程的虚拟地址空间。系统中有128个进程空间块编号,即0127,标号为X的进程空间块中的进程实际使用的虚拟地址空间为X0x02000000~X0x02000000+0x01FFFFFF,这个地址空间是系统中除CPU外的其他部分看到的该进程所占用的虚拟地址空间。如图3-35所示。