MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权。

许多年以前,当人们还在使用DOS或是更古老的操作系统的时候,计算机的内存还非常小,一般都是以K为单位进行计算,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图形界面的兴起还有用户需求的不断增大,应用程序的规模也随之膨胀起来,终于一个难题出现在程序员的面前,那就是应用程序太大以至于内存容纳不下该程序,通常解决的办法是把程序分割成许多称为覆盖块(overlay)的片段。覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由OS完成的,但是必须先由程序员把程序先进行分割,这是一个费时费力的工作,而且相当枯燥。人们必须找到更好的办法从根本上解决这个问题。不久人们找到了一个办法,这就是虚拟存储器(virtual memory).虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上。比如对一个16MB的程序和一个内存只有4MB的机器,操作系统通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由程序员进行分割。

相关概念

——地址范围、虚拟地址映射为物理地址 以及分页机制

任何时候,计算机上都存在一个程序能够产生的地址集合,我们称之为地址范围。这个范围的大小由CPU的位数决定,例如一个32位的CPU,它的地址范围是0~0xFFFFFFFF (4G),而对于一个64位的CPU,它的地址范围为0~0xFFFFFFFFFFFFFFFF (16E).这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址。与虚拟地址空间和虚拟地址相对应的则是物理地址空间和物理地址,大多数时候我们的系统所具备的物理地址空间只是虚拟地址空间的一个子集。这里举一个最简单的例子直观地说明这两者,对于一台内存为256M的32bit x86主机来说,它的虚拟地址空间范围是0~0xFFFFFFFF(4G),而物理地址空间范围是0x000000000~0x0FFFFFFF(256M)。

在没有使用虚拟存储器的机器上,虚拟地址被直接送到内存总线上,使具有相同地址的物理存储器被读写;而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到存储器管理单元MMU,把虚拟地址映射为物理地址。

大多数使用虚拟存储器的系统都使用一种称为分页(paging)机制。虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页帧(frame).页和页帧的大小必须相同。在这个例子中我们有一台可以生成32位地址的机器,它的虚拟地址范围从0~0xFFFFFFFF(4G),而这台机器只有256M的物理地址,因此他可以运行4G的程序,但该程序不能一次性调入内存运行。这台机器必须有一个达到可以存放4G程序的外部存储器(例如磁盘或是FLASH),以保证程序片段在需要时可以被调用。在这个例子中,页的大小为4K,页帧大小与页相同——这点是必须保证的,因为内存和外围存储器之间的传输总是以页为单位的。对应4G的虚拟地址和256M的物理存储器,他们分别包含了1M个页和64K个页帧。

1、将虚拟地址映射为物理地址

现代的多用户多进程操作系统,需要MMU,才能达到每个用户进程都拥有自己独立的地址空间的目标。使用MMU,操作系统划分出一段地址区域,在这块地址区域中,每个进程看到的内容都不一定一样。例如MICROSOFTWINDOWS操作系统将地址范围4M-2G划分为用户地址空间,进程A在地址0X400000(4M)映射了可执行文件,进程B同样在地址0X400000(4M)映射了可执行文件,如果A进程读地址0X400000,读到的是A的可执行文件映射到RAM的内容,而进程B读取地址0X400000时,则读到的是B的可执行文件映射到RAM的内容。

这就是MMU在当中进行地址转换所起的作用。

2、提供硬件机制的内存访问授权

多年以来,微处理器一直带有片上存储器管理单元(MMU),MMU能使单个软件线程工作于硬件保护地址空间。但是在许多商用实时操作系统中,即使系统中含有这些硬件也没采用MMU。

当应用程序的所有线程共享同一存储器空间时,任何一个线程将有意或无意地破坏其它线程的代码、数据或堆栈。异常线程甚至可能破坏内核代码或内部数据结构。例如线程中的指针错误就能轻易使整个系统崩溃,或至少导致系统工作异常。

就安全性和可靠性而言,基于进程的实时操作系统(RTOS)的性能更为优越。为生成具有单独地址空间的进程,RTOS只需要生成一些基于RAM的数据结构并使MMU加强对这些数据结构的保护。基本思路是在每个关联转换中“接入”一组新的逻辑地址。MMU利用当前映射,将在指令调用或数据读写过程中使用的逻辑地址映射为存储器物理地址。MMU还标记对非法逻辑地址进行的访问,这些非法逻辑地址并没有映射到任何物理地址。

这些进程虽然增加了利用查询表访问存储器所固有的系统开销,但其实现的效益很高。在进程边界处,疏忽或错误操作将不会出现,用户接口线程中的缺陷并不会导致其它更关键线程的代码或数据遭到破坏。目前在可靠性和安全性要求很高的复杂嵌入式系统中,仍然存在采无存储器保护的操作系统的情况,这实在有些不可思议。

采用MMU还有利于选择性地将页面映射或解映射到逻辑地址空间。物理存储器页面映射至逻辑空间,以保持当前进程的代码,其余页面则用于数据映射。类似地,物理存储器页面通过映射可保持进程的线程堆栈。RTOS可以在每个线程堆栈解映射之后,很容易地保留逻辑地址所对应的页面内容。这样,如果任何线程分配的堆栈发生溢出,将产生硬件存储器保护故障,内核将挂起该线程,而不使其破坏位于该地址空间中的其它重要存储器区,如另一线程堆栈。这不仅在线程之间,还在同一地址空间之间增加了存储器保护。

存储器保护(包括这类堆栈溢出检测)在应用程序开发中通常非常有效。采用了存储器保护,程序错误将产生异常并能被立即检测,它由源代码进行跟踪。如果没有存储器保护,程序错误将导致一些细微的难以跟踪的故障。实际上,由于在扁平存储器模型中,RAM通常位于物理地址的零页面,因此甚至NULL指针引用的解除都无法检测到。

MMU和CPU

1、X86系列的MMU

INTEL出品的80386CPU或者更新的CPU中都集成有MMU. 可以提供32BIT共4G的地址空间.

X86 MMU提供的寻址模式有4K/2M/4M的PAGE模式(根据不同的CPU,提供不同的能力),此处提供的是目前大部分操作系统使用的4K分页机制的描述,并且不提供ACCESS CHECK的部分。

涉及的寄存器

a) GDT

b) LDT

c) CR0

d) CR3

e) SEGMENT REGISTER

虚拟地址到物理地址的转换步骤

a) SEGMENT REGISTER作为GDT或者LDT的INDEX,取出对应的GDT/LDT ENTRY.

注意: SEGMENT是无法取消的,即使是FLAT模式下也是如此. 说FLAT模式下不使用SEGMENT REGISTER是错误的. 任意的RAM寻址指令中均有DEFAULT的SEGMENT假定. 除非使用SEGMENT OVERRIDE PREFⅨ来改变当前寻址指令的SEGMENT,否则使用的就是DEFAULT SEGMENT.

ENTRY格式

typedef struct

{

UINT16 limit_0_15;

UINT16 base_0_15;

UINT8 base_16_23;

UINT8 accessed : 1;

UINT8 readable : 1;

UINT8 conforming : 1;

UINT8 code_data : 1;

UINT8 app_system : 1;

UINT8 dpl : 2;

UINT8 present : 1;

UINT8 limit_16_19 : 4;

UINT8 unused : 1;

UINT8 always_0 : 1;

UINT8 seg_16_32 : 1;

UINT8 granularity : 1;

UINT8 base_24_31;

} CODE_SEG_DESCRIPTOR,*PCODE_SEG_DESCRIPTOR;

typedef struct

{

UINT16 limit_0_15;

UINT16 base_0_15;

UINT8 base_16_23;

UINT8 accessed : 1;

UINT8 writeable : 1;

UINT8 expanddown : 1;

UINT8 code_data : 1;

UINT8 app_system : 1;

UINT8 dpl : 2;

UINT8 present : 1;

UINT8 limit_16_19 : 4;

UINT8 unused : 1;

UINT8 always_0 : 1;

UINT8 seg_16_32 : 1;

UINT8 granularity : 1;

UINT8 base_24_31;

} DATA_SEG_DESCRIPTOR,*PDATA_SEG_DESCRIPTOR;

共有4种ENTRY格式,此处提供的是CODE SEGMENT和DATA SEGMENT的ENTRY格式. FLAT模式下的ENTRY在base_0_15,base_16_23处为0,而limit_0_15,limit_16_19处为0xfffff. granularity处为1. 表名SEGMENT地址空间是从0到0XFFFFFFFF的4G的地址空间.

b) 从SEGMENT处取出BASE ADDRESS 和LIMIT. 将要访问的ADDRESS首先进行ACCESS CHECK,是否超出SEGMENT的限制.

c) 将要访问的ADDRESS+BASE ADDRESS,形成需要32BIT访问的虚拟地址. 该地址被解释成如下格式:

typedef struct

{

UINT32 offset :12;

UINT32 page_index :10;

UINT32 pdbr_index :10;

} VA,*LPVA;

d) pdbr_index作为CR3的INDEX,获得到一个如下定义的数据结构

typedef struct

{

UINT8 present :1;

UINT8 writable :1;

UINT8 supervisor :1;

UINT8 writethrough:1;

UINT8 cachedisable:1;

UINT8 accessed :1;

UINT8 reserved1 :1;

UINT8 pagesize :1;

UINT8 ignoreed :1;

UINT8 avl :3;

UINT8 ptadr_12_15 :4;

UINT16 ptadr_16_31;

}PDE,*LPPDE;

e) 从中取出PAGE TABLE的地址. 并且使用page_index作为INDEX,得到如下数据结构

typedef struct

{

UINT8 present :1;

UINT8 writable :1;

UINT8 supervisor :1;

UINT8 writethrough:1;

UINT8 cachedisable:1;

UINT8 accessed :1;

UINT8 dirty :1;

UINT8 pta :1;

UINT8 global :1;

UINT8 avl :3;

UINT8 ptadr_12_15 :4;

UINT16 ptadr_16_31;

}PTE,*LPPTE;

f) 从PTE中获得PAGE的真正物理地址的BASE ADDRESS. 此BASE ADDRESS表名了物理地址的.高20位. 加上虚拟地址的offset就是物理地址所在了.

2、ARM系列的MMU

ARM出品的CPU,MMU作为一个协处理器存在。根据不同的系列有不同搭配。需要查询DATASHEET才可知道是否有MMU。如果有的话,一定是编号为15的协处理器。可以提供32BIT共4G的地址空间。

ARM MMU提供的分页机制有1K/4K/64K 3种模式. 本文介绍的是目前操作系统通常使用的4K模式。

涉及的寄存器,全部位于协处理器15.

ARM cpu地址转换涉及三种地址:虚拟地址(VA,Virtual Address),变换后的虚拟地址(MVA,Modified Virtual Address),物理地址(PA,Physical Address)。没有启动MMU时,CPU核心、cache、MMU、外设等所有部件使用的都是物理地址。启动MMU后,CPU核心对外发出的是虚拟地址VA,VA被转换为MVA供cache、MMU使用,并再次被转换为PA,最后使用PA读取实际设备。

ARM没有SEGMENT的寄存器,是真正的FLAT模式的CPU。给定一个ADDRESS,该地址可以被理解为如下数据结构:

typedef struct

{

UINT32 offset :12;

UINT32 page_index :8;

UINT32 pdbr_index :12;

} VA,*LPVA;

从MMU寄存器2中取出BIT14-31,pdbr_index就是这个表的索引,每个入口为4BYTE大小,结构为

typedef struct

{

UINT32 type :2; //always set to 01b

UINT32 writebackcacheable:1;

UINT32 writethroughcacheable:1;

UINT32 ignore :1; //set to 1b always

UINT32 domain :4;

UINT32 reserved :1; //set 0

UINT32 base_addr:22;

} PDE,*LPPDE;

获得的PDE地址,获得如下结构的ARRAY,用page_index作为索引,取出内容。

typedef struct

{

UINT32 type :2; //always set to 11b

UINT32 ignore :3; //set to 100b always

UINT32 domain :4;

UINT32 reserved :3; //set 0

UINT32 base_addr:20;

} PTE,*LPPTE;

从PTE中获得的基地址和上offset,组成了物理地址.

PDE/PTE中其他的BIT,用于访问控制。这边讲述的是一切正常,物理地址被正常组合出来的状况。

ARM/X86 MMU使用上的差异

⒈X86始终是有SEGMENT的概念存在. 而ARM则没有此概念(没有SEGMENT REGISTER.).

⒉ARM有个DOMAIN的概念. 用于访问授权. 这是X86所没有的概念. 当通用OS尝试同时适用于此2者的CPU上,一般会抛弃DOMAIN的使用.

linux mmu的实现的讲解_Linux_MMU相关推荐

  1. linux mmu的实现的讲解_Linux中的物理内存管理 [一]

    前面的文章介绍了Linux中虚拟地址空间的管理,本文将讨论Linux系统对物理内存的管理. NUMA 所谓物理内存,就是安装在机器上的,实打实的内存设备(不包括硬件cache),被CPU通过总线访问. ...

  2. linux mmu的实现的讲解_Linux中的段

    Intel 微处理器的段机制是从8086 开始提出的, 那时引入的段机制解决了从CPU 内部 16 位地址到20 位实地址的转换.为了保持这种兼容性,386 仍然使用段机制,但比以前复杂. 因此,Li ...

  3. linux mmu的实现的讲解_MMU解读

    转:https://blog.csdn.net/yueqian_scut/article/details/24816757 mmu页表也是放在内存中,mmu里有一个寄存器存放页表首地址,从而找到页表( ...

  4. linux下杀死进程全权讲解

    linux下杀死进程全权讲解 2009-10-27 08:57 佚名 linux 我要评论(0) 字号:T | T 本文将详细讲解linux杀死进程的多种命令,包含他们的作用,kill作用:根据进程号 ...

  5. Linux字符设备重命名,【收藏】Linux常用命令全称及讲解(五)

    今天小编 要跟大家分享的文章是关于Linux常用命令全称及讲解(五).从事IT行业的很多人都会使用Linux常用命令,但是知道这些常用命令全称的人并不多,让我们来看看这些常用命令对应的全称吧!小编精心 ...

  6. linux touch命令 全称,【收藏】Linux常用命令全称及讲解(八)

    今天小编要跟大家分享的文章是关于Linux常用命令全称及讲解(八).从事IT行业的很多人都会使用Linux常用命令,但是知道这些常用命令全称的人并不多,让我们来看看这些常用命令对应的全称吧!小编精心整 ...

  7. linux手机内存碎片整理软件,讲解macOS和Linux不用碎片整理的原因,而Windows需要碎片整理...

    本文为你讲解为什么 Windows 需要碎片整理,而 macOS 和 Linux 就不需要碎片整理的原因.在 Windows 系统中,传统(HDD)磁盘驱动器(非 SSD)通常使用一段时间都需要进行磁 ...

  8. linux+mmu工作原理,虚拟内存介绍及MMU工作原理(一)

    在linux,包括很多操作系统中,虚拟内存的概念十分重要.在使用windows的过程中,我们经常会遇到"虚拟内存不足"的提示,linux中有个所谓的swap分区,包括linux和u ...

  9. 【Linux C】access 函数讲解

    Linux access函数讲解_0729Liang-CSDN博客_access函数 函数: #include<unistd.h> int access(const char* pathn ...

  10. Linux 系统根目录的含义讲解

    Linux 系统根目录讲解 写这篇blog的意义是更好的理解CDH安装后,相关文件的位置.同理也可以更好理解系统目录设置的含义 目录总体结构 含义 /bin binary是二进制执行文件目录,主要用于 ...

最新文章

  1. CSV XLS文件区别
  2. BP神经网络的线性本质的理解和剖析-卷积小白的随机世界
  3. 机器学习入门学习笔记:(1)BP神经网络原理推导及程序实现
  4. Spring MVC - Hello World示例
  5. js与java的区别,JavaScript与Java的区别是什么呀?
  6. Cockroach DB 1.0发布
  7. 基于easyui开发Web版Activiti流程定制器详解(一)——目录结构
  8. vux radio 改造为 tree 代码片段
  9. 面试前可以在这里刷刷题,很巴适!(Java版)
  10. Android自己写的三款实用开关控件
  11. 机器学习重塑供应链管理的10个途径
  12. win10安装vc2015失败,尝试解决方案,目前有效
  13. 面对不稳定的百度网盘离线下载,这些备用方案可以帮你应急
  14. 时间序列信号处理系列-基于Python的同步压缩变换
  15. 2000-2019年中国地级市人均GDP
  16. 三维错切变换矩阵_三维基本几何变换矩阵.PPT
  17. Python基础教程:教你制作一个汇率换算程序
  18. 计算机科学与技术需要什么要求,计算机科学与技术专业需要掌握哪些技能?
  19. 【机器学习】泛化误差上界
  20. LNMP搭建HDwiki

热门文章

  1. WebSite设置首页或是加入收藏夹功能
  2. .NET 2.0中的企业库异常处理块
  3. 8.Mac PHPStorm 快捷键
  4. Java类与类,类与接口,接口与接口关系
  5. S20_DAY20--课堂笔记
  6. My Calendar I
  7. 很好的c++和Python混合编程文章
  8. hadoop-1.2.1运行过程中遇到的问题
  9. phpmyadmin提示SELECT `prefs` FROM `phpmyadmin`.`pma_table_uiprefs` ······
  10. 不借助第三方变量实现两个整数变量值的互换