一、内存地址
对于80x86微处理器,我们需要区分以下地址:
逻辑地址:这种寻址方式是x86才有的著名的分段结构,每一个逻辑地址都是由一个段和偏移量组成,偏移量指明了从段开始的地方实际地址之间的距离。
线性地址(也称虚拟地址):是一个32位无符号数,0x00000000~0xffffffff
物理地址:用于内存芯片级别内存寻址。他们从微处理器的地址引脚发送到内存总线上的电信号相对对应。
内存控制单元MMU通过一种称为分段单元的硬件电路把一个逻辑地址转换问线性地址;接着第二个分页单元的硬件电路把线性地址转换为物理地址。
分页单元也是段式管理单元的一部分,也是x86设备上独有的,为了兼容上古时期的寻址方式。
二、分页单元
分页单元是把线性地址转换成物理地址。其中一个关键任务就是把所请求的访问类型与线性地址的访问权限相比较,如果着此次的内存访问是无效的,就产生一个缺页异常。
线性地址被分成以固定长度为单位的组,称为页。页内部连续的线性地址被映射到连续的物理地址中。这样内核可以指定一个页的物理地址和其存取权限,而不用指定页所包含的全部线性地址的存取权限。例如一个32位的机器,线性地址最大可为4G,可以用4KB为一个页来划分,整个线性地址就被划分为一个tatol_page[2^20]的大数组,共有2的20个次方个页。这个大数组我们称之为页目录。目录中的每一个目录项,就是一个地址——对应的页的地址。
分页单元把所有的RAM分成固定长度的页框(又是也叫物理页)。每一个页框包含一个页,也就是说一个页框的长度与一个页的长度一致。页框是主存(RAM)的一部分,因此是一个存储区域。
把线性地址映射到物理地址的数据结构成为页表。页表存放在主存中,在启用分页单元之前必须由内核对页表进行适当的初始化
典型的分页管理下虚拟地址的内存寻址方式:
已知一个虚拟地址0x01AF5518, 则转换的过程如下:
注意: *这里讨论的以Windows下普通模式分页的情况, 也就是2级页表的情况*
1.首先把虚拟地址拆分成3个部分(低12位, 中10位, 高10位), 换成2进制如下:
-> 0000 0001 1010 1111 0101 0101 0001 1000
按照10, 10, 12的位数重新排列后
-> (页目录索引)00 000 00110, (页表项索引)10 1111 0101, (偏移)0101 0001 1000
换算成十六进制后可以得到如下结果
页目录索引 = 6, 页表项索引 = 0x2f5 , 偏移 = 0x518
2. 根据当前的CR3寄存器中的物理地址定位页目录表基址
Cr3中存放的是物理地址, 这个物理地址指向进程的页目录表基址, 由此可以得到
页目录表基址(PDE) = Cr3 = 0xAA0E5000
3. 计算页表项的地址
页表地址存放在页目录表(PDE)中的第6个项目中, 也就是
[0xAA0E5000 + 4 * 6] = [0xAA0E5018] = 0x3D955867, 其中0x00000867为该页表属性值, PTE = 0x3D955000
假设 [0xAA0E5018] = 0x3D955867,0xAA0E5018地址存放的内容为0x3D955867。
3. 计算页面物理地址
我们要找的页面在这个页表中的第0x2f5项, 所以虚拟地址所在的页的物理地址为
[0x3D955000 + 0x2f5 * 4] = [0x3D955BD4] =
假设[0x3D955BD4] = 0x7095e847, 页面的物理地址 x0x7095e000, 0x00000847表示的是页面属性
4. 计算最终的物理地址
由虚拟地址分离的偏移可以计算出最终的物理地址为
0x7095E000 + 0x00000518 = 0x7095E518
1、分页单元中,页目录是唯一的,它的地址放在CPU的cr3寄存器中,是进行地址转换的开始点。万里长征就从此长始了。
2、每一个活动的进程,因为都有其独立的对应的虚似内存(页目录也是唯一的),那么它也对应了一个独立的页目录地址。——运行一个进程,需要将它的页目录地址放到cr3寄存器中,将别个的保存下来。
3、每一个32位的线性地址被划分为三部份,面目录索引(10位):页表索引(10位):偏移(12位)
4、依据以下步骤进行转换:
① 从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
② 根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
③ 根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
④ 将页的起始地址与线性地址中最后12位相加,得到最终我们想要的葫芦;
linux采用4级分页,具体分页单元是如何工作参考https://blog.csdn.net/gatieme/article/details/52403013
三、硬件高速缓存
微处理器的始终频率GHz,而动态RAM的芯片的存取时间是时钟周期的几百倍,为了缩小CPU和RAM之间的速度不匹配,引入的硬件高速缓存,基于著名的局部性原理
四、转换后援缓冲器(TLB)
除了通用硬件高速缓存之外,80x86处理器还包含了另一个称为TLB的高速缓存用于加快线性地址的转换。当一个线性地址被第一次使用时,通过慢速访问RAM的页表计算出物理地址。这时,物理地址被存放在一个TLB中,以便以后对同一个线性地址的引用可以快速的转换。
在多处理系统中,每个CPU都有自己的TLB,这叫做该CPU的本地TLB。当进程切换时或者改变内核页表项时,TLB都会无效。
五、物理内存布局
一般来说,Linux内核安装在RAM中从物理地址0x00100000开始的地方。前面的这些预留内存是留给BIOS使用。