内存分段
1.1 分段机制概述
1.1.1 分段机制产生的原因
对于分段机制,要从Intel的微处理器的8086开始说起,刚开始内存空间比较小,内存寻址采用的是直接访问物理地址的方式。由于技术的发展,计算机做的事情越来越多,程序也越来越大,为了更大的内存空间,把地址总线扩展到20位。但是,对于内存设计,一个很尴尬的问题产生了,之前的设计CPU的ALU宽度只有16位,也就是说,ALU不能访问20位的地址空间,那时就设计了段机制来处理这种情况。为了坚持这种兼容性,386依然运用段机制,直至现在的64位处理器已经看不到段机制的身影。
1.1.2 硬件分段机制
在内存分段管理中,程序是由若干个逻辑分段组成的,如可由代码分段、数据分段、堆段、栈段组成。不同的段是有不同的属性的,所以就用分段的形式把这些段分离出来。
分段机制下的虚拟地址由两部分组成,段选择子和段内偏移量。
-
段选择子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。
-
虚拟地址中的段内偏移量应该位于 0 和段界限之间,如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。
内存分段下的地址映射过程:
- 虚拟地址由段选择子和段偏移量组成;
- 通过段选择子中的段号从段表中找到对应的段内描述符;
- 段描述符里提供了段基址,加上虚拟地址上的段偏移量得到物理地址;
1.1.3 不足之处
产生外部内存碎片。
内存交换的效率低。
1.2 分段机制
1.2.1 段选择子
段选择子(又称段选择符)是段的一个十六位标志符,段选择子并不直接指向段,而是指向段描述符表中定义段的段描述符。
段选择子包括三个字段的内容:
- 请求特权级RPL:0代码核心态,1代表用户态;
- 表指引标志TL:0表示描述符在GDT中,1表示描述符在LDT中;
- 索引值:给出了描述符在GDT或LDT表中的索引项号。
下面是一些段选择子的示例:
1.2.2 段描述符
段描述符表是段描述符的一个数组,如下图所示,描述符表的长度可变,最多可以包含8192个8byte描述符。有两个描述符表,全局描述符表GDT(Global descriptor table),局部描述符表LDT(Local descriptor table),由段选择符的bit[2]会选择到对应的GDT表还是LDT表去拿到对应的段基址。
而对于段描述符,每个段描述符的长度是8字节,含有三个主要字段:段基址、段限长和段属性。段描述符通常由编译器、链接器、加载器或者操作系统来创建,绝不可能由应用程序来创建。
段描述符通用格式如下:
了解了这个过程,我们来总体梳理下,如果使用分段机制,那么怎么使虚拟地址转到对应的物理地址空间呢?转化过程如下图所示 :
1、取出虚拟地址空间中的段选择子,根据TI位判断段描述符是存储在GDT还是LDT中;
2、段选择子中的index*8,也就是左移3位,就是段描述符在GDT中的位置,再加上GDT的基地址,就是段描述符的地址,从而取出段描述符;
3、段描述符中保存了该段的基地址,加上虚拟地址中的偏移量就是对应到的物理地址空间。