1.MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问受权,多用户多进程操做系统。程序员
2.虚拟内存由来:许多年之前,当人们还在使用DOS或是更古老的操做系统的时候,计算机的内存还很是小,通常都是以K为单位进行计算,相应的,当时的程序规模也不大,因此内存容量虽然小,但仍是能够容纳当时的程序。但随着图形界面的兴起还有用户需求的不断增大,应用程序的规模也随之膨胀起来,终于一个难题出如今程序员的面前,那就是应用程序太大以致于内存容纳不下该程序,一般解决的办法是把程序分割成许多称为覆盖块(overlay)的片断。覆盖块0首先运行,结束时他将调用另外一个覆盖块。虽然覆盖块的交换是由OS完成的,可是必须先由程序员把程序先进行分割,这是一个费时费力的工做,并且至关枯燥。人们必须找到更好的办法从根本上解决这个问题。不久人们找到了一个办法,这就是虚拟存储器(virtual memory).虚拟存储器的基本思想是程序,数据,堆栈的总的大小能够超过物理存储器的大小,操做系统把当前使用的部分保留在内存中,而把其余未被使用的部分保存在磁盘上。好比对一个16MB的程序和一个内存只有4MB的机器,操做系统经过选择,能够决定各个时刻将哪4M的内容保留在内存中,并在须要时在内存和磁盘间交换程序片断,这样就能够把这个16M的程序运行在一个只具备4M内存机器上了。而这个16M的程序在运行前没必要由程序员进行分割。架构
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它一般是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在须要时进行数据交换。目前,大多数操做系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。app
咱们执行下面这些指令(本例子的指令不针对任何特定机型,都是伪指令)
例1:
MOVE REG,0 //将0号地址的值传递进寄存器REG.
虚拟地址0将被送往MMU,MMU看到该虚地址落在页0范围内(页0范围是0到4095),从上图咱们看到页0所对应(映射)的页框为2(页框2的地址范围是8192到12287),所以MMU将该虚拟地址转化为物理地址8192,并把地址8192送到地址总线上。内存对MMU的映射一无所知,它只看到一个对地址8192的读请求并执行它。MMU从而把0到4096的虚拟地址映射到8192到12287的物理地址。spa
例2:
MOVE REG,8192
被转换为
MOVE REG,24576
由于虚拟地址8192在页2中,而页2被映射到页框6(物理地址从24576到28671)操作系统
例3:
MOVE REG,20500
被转换为
MOVE REG,12308
虚拟地址20500在虚页5(虚拟地址范围是20480到24575)距开头20个字节处,虚页5映射到页框3(页框3的地址范围是 12288到16383),因而被映射到物理地址12288+20=12308。3d
经过适当的设置MMU,能够把16个虚页隐射到8个页框中的任何一个,可是这个方法并无有效的解决虚拟地址空间比物理地址空间大的问题。从上图中咱们能够看到,咱们只有8个页框(物理地址),但咱们有16个页(虚拟地址),因此咱们只能把16个页中的8个进行有效的映射。咱们看看例4会发生什么状况htm
MOV REG,32780
虚拟地址32780落在页8的范围内,从上图总咱们看到页8没有被有效的进行映射(该页被打上X),这是又会发生什么?MMU注意到这个页没有被映射,因而通知CPU发生一个缺页故障(page fault).这种状况下操做系统必须处理这个页故障,它必须从8个物理页框中找到1个当前不多被使用的页框并把该页框的内容写入外围存储器(这个动做被称为page copy),随后把须要引用的页(例4中是页8)映射到刚才释放的页框中(这个动做称为修改映射关系),而后重新执行产生故障的指令(MOV REG,32780)。假设操做系统决定释放页框1,那么它将把虚页8装入物理地址的4-8K,并作两处修改:首先把标记虚页1未被映射(原来虚页1是被影射到页框1的),以使之后任何对虚拟地址4K到8K的访问都引发页故障而使操做系统作出适当的动做(这个动做正是咱们如今在讨论的),其次他把虚页8对应的页框号由X变为1,所以从新执行MOV REG,32780时,MMU将把32780映射为4108。blog
7.索引
个人s3c2410上配置的SDRSAM大小为64M,该SDRAM的物理地址范围是0x3000 0000~0x33FF FFFF(属于Bank 6),因为1个Section的大小是1M,因此该物理空间能够被分红64个物理段(页框).进程
在Section模式下,送进MMU的虚拟地址(注1)被分为两部分(这点和咱们上面举的例子是同样的),这两部分为 Descriptor Index(至关于上面例子的Page Index)和 Offset,descript index长度为12bit(2^12=4096,从这个关系式你能看出什么?:) ),Offset长度为20bit(2^20=1M,你又能看出什么?:)).观察一下一个描述符(Descriptor)中的Section Base Address部分,它长度为12 bit,里面的值是该虚拟段(页)映射成的物理段(页框)的物理地址前12bit,因为每个物理段的长度都是1M,因此物理段首地址的后20bit老是为0x00000(每一个Section都是以1M对齐),肯定一个物理地址的方法是 物理页框基地址+虚拟地址中的偏移部分=Section Base Address<<20+Offset ,呵呵,可能你有点糊涂了,仍是举一个实际例子说明吧。
假设如今执行指令MOV REG, 0x30000012,虚拟地址的二进制码为00110000 00000000 00000000 00010010,前12位是Descriptor Index= 00110000 0000=768,故在Translation Table里面找到第768号描述符,该描述的Section Base Address="0x0300",也就是说描述符所描述的虚拟段(页)所映射的物理段(页框)的首地址为0x3000 0000(物理段(页框)的基地址=Section Base Address左移20bit=0x0300<<20=0x3000 0000),而Offset=000000 00000000 00010010=0x12,故虚拟地址0x30000012映射成的物理地址=0x3000 0000+0x12=0x3000 0012(物理页框基地址+虚拟地址中的偏移)。你可能会问怎么这个虚拟地址和映射后的物理地址同样?这是由咱们定义的映射规则所决定的。在这个例子中咱们定义的映射规则是把虚拟地址映射成和他相等的物理地址。咱们这样书写映射关系的代码:
void mem_mapping_linear(void)
{
unsigned long descriptor_index, section_base, sdram_base, sdram_size;
sdram_base=0x30000000;
sdram_size=0x 4000000;
for (section _base= sdram_base,descriptor_index = section _base>>20;
section _base < sdram_base+ sdram_size;
descriptor_index+=1;section _base +=0x100000)
{
*(mmu_tlb_base + (descriptor_index)) = (section _base>>20) | MMU_OTHER_SECDESC;
}
}
上面的这段段代码把虚拟空间0x3000 0000~0x33FF FFFF映射到物理空间0x3000 0000~0x33FF FFFF,因为虚拟空间与物理空间空间相吻合,因此虚拟地址与他们各自对应的物理地址在值上是一致的。当初始完Translation Table以后,记得要把Translation Table的首地址(第0号描述符的地址)加载进协处理器CP15的Control Register2(2号控制寄存器)中,该控制寄存器的名称叫作Translation table base (TTB) register。
8.以上讨论的是descriptor中的Section Base Address以及虚拟地址和物理地址的映射关系,然而MMU还有一个重要的功能,那就是访问控制机制(Access Permission )。简单说访问控制机制就是CPU经过某种方法判断当前程序对内存的访问是否合法(是否有权限对该内存进行访问),若是当前的程序并无权限对即将访问的内存区域进行操做,则CPU将引起一个异常,s3c2410称该异常为Permission fault,x86架构则把这种异常称之为通用保护异常(General Protection),什么状况会引发Permission fault呢?好比处于User级别的程序要对一个System级别的内存区域进行写操做,这种操做是越权的,应该引发一个Permission fault,搞过x86架构的朋友应该听过保护模式(Protection Mode),保护模式就是基于这种思想进行工做的,因而咱们也能够这么说:s3c2410的访问控制机制其实就是一种保护机制。