1,基本概念
一个程序运行时没必要全部都同时装入内存,只需要把当前需要运行的部分装入内存即可,这样就使得一个大程序可以在较小的内存中运行,也使得内存中可以同时装入更多的程序并发执行,从用户角度看,该系统拥有的内存容量比实际的内存容量大的多,这样的存储器称为虚拟存储器。虚拟存储器从逻辑上对内存容量进行了扩充,用户看到的大容量是虚的。
在没有使用虚拟存储器的机器上,地址被直接送到内存总线上,使具有相同地址的物理存储器被读写;而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到存储器管理单元MMU,把虚拟地址映射为物理地址。(即MMU把虚拟地址空间和物理地址空间给隔开了)
虚拟地址空间:大小由CPU的位数决定,例如在一个32位的CPU系统中,这个虚拟内存地址范围是0~0xFFFFFFFF (4G),这个地址范围称为虚拟地址空间。
虚拟地址:虚拟地址空间中的某一个地址我们称之为虚拟地址。
物理地址空间和物理地址就是对应实际的内存。
页表(Page Table):把虚拟内存转换为物理内存,一般有两种办法,其一用一个数学公式进行转换;另一个就是用表格存储虚拟地址对应的物理地址,这个表格就称为页表。页表有一个个条目(Entry)(条目也称为描述符)组成,每个条目存储了一段虚拟地址对应的物理地址及其访问权限,或者下一级页表的地址。我们以两级页表为例简单说一下 虚 到 实的转换过程:开始是页表基址寄存器(存了一级页表的基地址),这样就来到了一级页表,根据要找的虚拟地址找到一级页表中的条目,如果此条目是段描述符,则返回物理地址结束;如果是二级页表的描述符,则继续利用虚拟地址在 此二级也页表中找到条目,如果找到的条目是页描述符,则返回物理地址,结束。
单独说一下一级页表,32位CPU的虚拟地址空间为4GB,一级页表中使用了4096个描述符来表示这4GB空间,即每个描述符对应1MB的虚拟地址,这4096个描述符中存储了它各种对应的1MB物理空间的起始地址 或者 下一级页表的地址。
TLB(Translation Lookaside Buffer)转换检测缓冲区是一个内存管理单元,用于改进虚拟地址到物理地址转换速度的缓存。
CPU每次拿着虚拟内存去找物理地址,从概念上说,这个转换需要遍历页表,如果页表是二级页表,就需要2次内存访问才能拿个物理地址,读写数据还得访问一次。这一遍遍访问内存,遍历页表太慢。所以出现了TLB(常用的几十个虚拟地址与物理地址的对应表,当然满了会有算法去更新),CPU发出虚拟地址,MMU先访问TLB,如果有这个虚拟地址则直接用这个描述符进行地址转换和权限检查,没有再去遍历页表,找到描述符进行那俩工作,并把描述符填入TLB(TLB已满,用round-robin算法找到一个条目,覆盖它)。
Cache高速缓冲存储器,在主存和CPU通用寄存器间设置的一个高速的小存储器,,把正在执行的指令地址附近的指令或数据从主存中调入这个存储器,供CPU在一段时间内使用。启用Cache后,CPU读数据,如果Cache中有这个数据的复本则直接返回,否则从主存中读取。
TLB 和 Cache的都是一种缓存。
2,MMU
内存管理单元(Memory Management Unit)简称MMU,两个功能:虚拟地址到物理地址的映射;提供硬件机制的内存访问权限检查。
1)虚拟地址到物理地址的映射
现代的多用户多进程操作系统,通过MMU使每个用户进程都拥有自己独立的地址空间:地址映射功能使得各进程拥有“看起来”一样的地址空间。
例如WINDOWS操作系统将地址范围4M-2G划分为用户地址空间,进程A在地址0X400000(4M)映射了可执行文件,进程B同样在地址0X400000(4M)映射了可执行文件,如果A进程读地址0X400000,读到的是A的可执行文件映射到RAM的内容,而进程B读取地址0X400000时,则读到的是B的可执行文件映射到RAM的内容。
ARM的CPU上地址转换有3个概念:虚拟地址VA、变换后的虚拟地址MVA、物理地址PA。
- 没启动MMU时,CPU、cache、MMU、外设等所有部件使用的是物理地址;
- 启动MMU之后,CPU对外发出虚拟地址VA,VA被转换为MVA供cache、MMU使用,MVA在这里被转换为PA,最后使用PA读写实际的硬件设备(内部寄存器或外接设备)。
CPU核看到的、用到的只是虚拟地址VA。实际设备看不到VA和MVA,读写他们时使用的是物理地址PA。
2)提供硬件机制的内存访问权限检查
简单来说就是决定一块内存是否允许读,是否允许写。页表描述符的域(domain),描述符的AP位,CP15寄存器C3,CP15寄存器C1D R/S/A位。MMU根据这些值来进行权限检查。
《嵌入式Linux应用开发完全手册》