MMU的作用及工作过程

来源:互联网 发布:微盘源码下载 编辑:程序博客网 时间:2024/06/06 13:55

以下内容摘自《步步惊芯——软核处理器内部设计分析》一书的第10章 MMU剖析

MMU 的作用及工作过程

      MMU ( Memory Management Unit )是内存管理单元的简称,读者朋友在学习嵌入式的时候应该听说过 µCLinux ,这是适合没有 MMU 的微控制器使用的嵌入式Linux 操作系统,比如 ARM7 。由于没有 MMU ,所以在 µCLinux 上实现多任务功能是一个非常棘手的问题。从而引出了本节的关注点: MMU 的作用是什么?简单地说, MMU 的作用有两点:地址翻译、内存保护。

1 、地址翻译

      在处理器上一般会运行一个操作系统,如 Linux ,用户编写的源程序需要经过编译、链接得到可执行文件,然后被操作系统加载执行。编译、链接的过程在第 2 章实验环境搭建中有过描述,在链接的时候需要指定一个链接描述脚本,链接描述脚本有很多作用,其中一项是控制可执行文件中 Section 和符号的内存布局,也就是控制可执行程序在内存中是如何放置的,操作系统会按照可执行文件的要求将其加载到内存对应地址并执行。假如用户 A 编写了程序 ProgramA ,并且 ProgramA 占用的内存空间是 0x100-0x200 ,用户 B 编写了程序 ProgramB ,并且 ProgramB 要求的内存空间也是 0x100-0x200 ,这是完全有可能的,因为给操作系统提供程序的用户很多,不可能限定每个用户使用不同部分的内存。这样当 ProgramA 被加载执行时, ProgramB 就不能被加载执行,一旦 ProgramB 也被加载了就会破坏 ProgramA 的执行,因为后者会覆盖 ProgramA 占用的内存。为了解决这个问题,将操作系统和处理器都做了修改,添加了 MMU ,在其中进行地址翻译,程序加载入内存的时候为其建立地址翻译表,处理器执行不同程序的时候使用不同的地址翻译表,如图 10.1 所示。

      ProgramA 被加载到地址 0x500-0x600 处, ProgramB 被加载到地址 0x700-0x800 处,同时建立了各自的地址翻译表,当处理器要执行 ProgramB 时,会使用ProgramB 对应的地址翻译表,比如读取 ProgramB 地址 0x100 处的指令,那么经过地址翻译表可知 0x100 对应实际内存的 0x700 处,所以实际读取的就是 0x700 处的指令。同样的,当处理器要执行 ProgramA 时,会使用 ProgramA 对应的地址翻译表,这样就避免了之前提到的内存冲突问题,有了 MMU 的支持,操作系统就可以轻松实现多任务了。

      图 10.1 中 CPU 给出的地址称之为虚拟地址( OR1200 中称之为有效地址 EA),经过 MMU 翻译后的地址称之为物理地址。

      MMU 的地址翻译功能还可以为用户提供比实际大得多的内存空间。用户在编写程序的时候并不知道运行该程序的计算机内存大小,如果在链接的时候指定程序被加载到地址 Addr 处,而运行该程序的计算机内存小于 Addr ,那么程序就无法执行,有了 MMU 后,程序员就不用关心实际内存大小,可以认为内存大小就是“ 2^ 指令地址宽度”。 MMU 会将超过实际内存的虚拟地址翻译为物理地址进行访问。

      地址翻译表存储在内存中,如果采用图 10.1 中的方式:地址翻译表的表项是一个虚拟地址对应一个物理地址,那么会占用太多的内存空间,为此,需要修改翻译方式,常用的有三种:页式、段式、段页式,这也是三种不同的内存管理方式。

      页式内存管理将虚拟内存、物理内存空间划分为大小固定的块,每一块称之为一页,以页为单位来分配、管理、保护内存。此时 MMU 中的地址翻译表称为页表(Page Table ),每个任务或进程对应一个页表,页表由若干个页表项( PTE : Page Table Entry )组成,每个页表项对应一个虚页,内含有关地址翻译的信息和一些控制信息。在页式内存管理方式中地址由页号和页内位移两部分组成,其地址翻译方式如图 10.2 所示。

      使用虚拟地址中的虚页号查询页表得到对应的物理页号,然后与虚拟地址中的页内位移组成物理地址。比如:页大小是 256 字节,虚拟地址是 0x104 ,可知对应的虚页号是 0x1 ,页内位移是 0x4 ,假如通过页表翻译得到的对应物理页号是 0x7 ,那么0x104 对应的物理地址就是 0x704 。使用页表方式进行地址翻译可以有效减少地址翻译表占用的内存空间,还是以图 10.1 为例,页大小是 256 字节,此时每个程序对应的页表就只有两项,如图 10.3 所示。

      段式内存管理将虚拟内存、物理内存空间划分为段进行管理,段的大小取决于程序的逻辑结构,可长可短,一般将一个具有共同属性的程序代码和数据定义在一个段中。每个任务和进程对应一个段表( Segment Table ),段表由若干个段表项( STE: Segment Table Entry )组成,内含地址映像信息(段基址和段长度)等内容。在段式虚拟存储器中,地址分为段号、段内位移两部分,使用段表进行地址翻译的过程与使用页表进行地址翻译的过程是相似的。

      段页式内存管理是在内存分段的基础上再分页,即每段分成若干个固定大小的页。每个任务或进程对应有一个段表,每段对应有自己的页表。在访问存储器时,由CPU 经页表对段内存储单元进行寻址。

      OR1200 处理器中的 MMU 使用页表进行地址翻译,所以本章对段式、段页式不做过多着墨,同时,下文介绍内存保护、 TLB 时都默认是页式内存管理。

      2 、内存保护

       MMU 除了具有地址翻译的功能外,还提供了内存保护功能。采用页式内存管理时可以提供页粒度级别的保护,允许对单一内存页设置某一类用户的读、写、执行权限,比如:一个页中存储代码,并且该代码不允许在用户模式下执行,那么可以设置该页的保护属性,这样当处理器在用户模式下要求执行该页的代码时, MMU 会检测到并触发异常,从而实现对代码的保护。下文在分析 OR1200 处理器中 MMU 模块时会具体介绍内存保护的实现机制。

0 0