linux内存管理-分段管理

      内存的管理方式有分段管理和分页管理两种;

      分段管理是从逻辑内存的角度来分的,就是将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息;

      分页是从物理内存的角度,将内存按页划分,便于减小内存碎片;

 

      分段管理的由来:

       最早的处理器存储空间较小,采用的是直接物理内存访问的方式,这种称为实模式;为了支持更大的存储器,在8086时将地址总线扩展到20位,可以支持1M的寻址空间;
但8086的数据处理总线为16位,无法直接寻址1MB内存空间,所以8086提供了段地址加偏移地址的地址转换机制,就是我们常见的”段地址(16位):偏移地址(16位或有效地址)”,实际的计算方法为:”段地址*0x10H+偏移地址”;作为段地址的数据是放在段寄存器中的(16位),而作为位偏移地址的数据则是通过8086提供的寻址方式来计算而来的(16位);
下面简单的示意图简单的描述计算过程:
+-----------------+
|       20        |  20位地址总线
+-----------------+
+------------+
|      16    |       16位段地址
+------------+
    +-------------+
    |    12  | 4  |  16位内存地址(段内偏移量)
    +--------+----+

实际物理地址 = (段寄存器地址 << 4) + (CPU 提交的访存地址)


       分段地址转换过程:

              CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步:
首先,将给定一个逻辑地址(段标识符:段内偏移),CPU要利用其段式内存管理单元,先将这个逻辑地址转换成一个线性地址,其次,再利用其页式内存管理单元,转换为最终物理地址。




       一个逻辑地址由两部份组成,段标识符: 段内偏移量。段标识符是由一个16位长的字段组成,称为段选择符。其中前13位是一个索引号。后面3位包含一些硬件细节,如图

         索引号就是“段描述符(segment descriptor)”,段描述符具体描述了一个段。这样,很多个段描述符,就组了一个数组,叫“段描述符表”,这样,可以通过段标识符的前13位,直接在段描述符表中找到一个具体的段描述符,这个描述符就描述了一个段,每一个段描述符由8个字节组成,如下图:




其中段描述符表又分为GDT跟LDT,一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每个进程自己的,就放在所谓的“局部段描述符表(LDT)”中;

而GDT或者LDT的选择要看段描述符的T1字段的值,0表示用GDT,1用LDT;

总结下逻辑地址转换成线性地址的过程:


首先,给定一个完整的逻辑地址[段选择符:段内偏移地址],
1、看段选择符的T1=0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地址和大小。我们就有了一个数组了。
2、拿出段选择符中前13位,可以在这个数组中,查找到对应的段描述符,这样,它了Base,即基地址就知道了。
3、把Base + offset,就是要转换的线性地址了。





你可能感兴趣的:(linux内存管理-分段管理)