之前都是编写裸机程序,从来不关心MMU是个什么鬼。现在研究各种OS(LINUX/liteOS)内核源码的时候,每一个都要关心MMU的初始化和移植。总是一知半解混混沌沌肯定是不行的,今天结合各种资料彻底搞懂它!
以下内容摘自《步步惊芯——软核处理器内部设计分析》一书的第10章 MMU剖析
MMU作用
MMU(Memory Management Unit)是内存管理单元的简称。
读者朋友在学习嵌入式的时候应该听说过µCLinux,这是适合没有MMU的微控制器使用的嵌入式Linux操作系统,比如ARM7。由于没有MMU,所以在µCLinux上实现多任务功能是一个非常棘手的问题。从而引出了本节的关注点:MMU的作用是什么?简单地说,MMU的作用有两点:地址翻译、内存保护。
1、地址翻译
在处理器上一般会运行一个操作系统,如Linux,用户编写的源程序需要经过编译、链接得到可执行文件,然后被操作系统加载执行。编译、链接的过程在第2章实验环境搭建中有过描述,在链接的时候需要指定一个链接描述脚本,链接描述脚本有很多作用,其中一项是控制可执行文件中Section和符号的内存布局,也就是控制可执行程序在内存中是如何放置的。操作系统会按照可执行文件的要求将其加载到内存对应地址并执行。(在裸机程序时,就需要boot程序把用户程序从flash中搬运到链接脚本规定的首地址开始的内存空间去。)
假如:用户A编写了程序ProgramA,并且ProgramA占用的内存空间是0x100-0x200,用户B编写了程序ProgramB,并且ProgramB要求的内存空间也是0x100-0x200,这是完全有可能的,因为给操作系统提供程序的用户很多,不可能限定每个用户使用不同部分的内存。这样当ProgramA被加载执行时,ProgramB就不能被加载执行,一旦ProgramB也被加载了就会破坏ProgramA的执行,因为后者会覆盖ProgramA占用的内存。
为了解决这个问题,将操作系统和处理器都做了修改,添加了MMU,在其中进行地址翻译,程序加载入内存的时候为其建立地址翻译表,处理器执行不同程序的时候使用不同的地址翻译表,如图10.1所示。
ProgramA被加载到地址0x500-0x600处,ProgramB被加载到地址0x700-0x800处,同时建立