虚拟内存管理(一)

很久以前就想写一下关于虚拟内存管理方面的文章,主要还是写给自己看的。原因主要是自己对Linux虚拟内存管理也是一知半解,写一篇博客,记录一下自己这几天的学习笔记,留着以后做参考。

这一篇主要讲一下虚拟地址到物理地址的转换。主要参考《深入理解计算机系统》一书。

关于逻辑地址、线性地址和物理地址

物理地址:

物理地址可以想象成实际物理存储上的地址

线性地址:

线性地址也可以叫做虚拟地址,是一个不真实的地址,可以理解为页式管理中的地址

逻辑地址:

逻辑地址与线性地址一样,是一个不真实的地址,用于Intel段式管理中的地址

三个地址的转换关系:

逻辑地址–>线性地址–>物理地址

逻辑地址–>线性地址

逻辑地址由两部分组成,段标识符和段内偏移地址。段标识符是有个16位长的字段组成,叫做段选择符。其中高13位是一个索引号,如下图:

索引号用于索引段描述符表的某一段描述符,段描述符格式如下图:

在Linux下,段描述符的Base都是0,因此逻辑地址的段内偏移量就是线性地址,接下来看一下线性地址怎样转换成物理地址的。

线性地址–>物理地址

首先宏观上的看一下线性地址(虚拟地址)到物理地址的转换

虚拟地址高位有一个页表索引,通过页表索引可以在页表中找到对应的一个页表入口(Page Table Entry),在PTE中可以得到物理页号,然后在加上原先在虚拟地址中的偏移量,就会定位到最终的地址。

基本流程

如上图是一个正常的命中流程:

  1. 处理器生成一个虚拟地址,并将其给MMU
  2. MMU生成一个PTE地址,从高速缓存/主存中请求获取
  3. 高速缓存/主存将PTE数据传回MMU
  4. MMU生成物理地址,传给高速缓存/主存
  5. 高速缓存/主存将数据传回处理器

上图是发生缺页中断的情况,高速缓存/主存会将牺牲页换出,将新页换进。

利用TLB加速地址翻译

TLB全称翻译后备缓冲器(Translation Lookaside Buffer),位于MMU内存,其实就是缓存住了一些PTE,那么MMU就不需要从高速缓存/主存中获取PTE了。

多级页表

如果是32位的虚拟地址空间,一个页的大小为4K,那一张页表就有1M个PTE,如果每个PTE的大小为4个字节,那么页表占用内存大小为4MB。如果是64位机器,它的寻址位数是48位,那页表就更大了。
解决方式是讲页表分为多级,如下图:

地址翻译的过程基本就差不多了。