1.段选择符和分段寄存器

            一个逻辑地址包括两部分:段标识符 和 段内相对偏移地址。段标识符是一个被叫做段选择符(selector)的16比特的域,而偏移地址是一个32比特的域。

           为了方便快速检索段选择符,处理器提供了6个分段寄存器(segmentation register)来缓存段选择符,它们是:cs,ss,ds,es,fs和gs. 虽然只有这6个寄存器,但程序可以复用同一个寄存器来实现不同的目的,只需要把该寄存器的内容保存到内存中,在随后需要的时候可以恢复它的内容。需要注意的是,cs、ss、ds有专门的用途。请看下面介绍:

        cs-----内存段寄存器,指向含有代码指令的段;cs寄存器还有一个重要的功能:用于区分用户模式和内核模式,它包含一个指定当前优先级别(CPL, current priviledge level)的的2比特的域。如果该域的值为0,表明优先级最高;如果该值为3,表明最低的优先级。 Linux只使用了0和3,用以区分内核模式和用户模式。

        ss-----堆栈段寄存器,指向包含当前程序栈的段;

        ds-----数据段寄存器,指向包含静态和全局数据的段。

       其它三个,即es,fs和gs,都是通用分段寄存器,可以指向任意类型的段。

2.段描述符

          每一个段都由一个8字节的段描述符来表示,它描述了段的特征。段描述符要么存储在全局描述符表(GDT)里,要么存储在本地描述符表(LDT)里.

        通常只定义了一个GDT。然而,每个进程都允许有自己的LDT,如果进程需要额外创建除了GDT里描述的之外的段。主存里GDT的地址和大小都包含在gdtr控制寄存器中,而当前正在使用的LDT的地址和大小则包含在ldtr控制寄存器中。

          BASE:段的第一个字节的线性地址。

          G:如果为0,则段的大小用字节表示。

          Limit:保存了段中最后一个存储单元的偏移值,因此与segment的长度、大小是绑定在一起的。如果G为0,则LIMIT的大小范围为1字节~1MB;反之, LIMIT大小范围为4KB~4GB.

          S:如果为0,表示为一个系统段(system segment);反之,为一个普通的数据段或代码段。系统段里保存了关键的数据结构,如LDT.

         Type:描述segment的类型。

          DPL:描述符优先级别。主要用于对segment的访问进行限制。

          P:描述段是否在内存中存在的标记。

 

3.对段描述符的快速访问的实现

       我们知道,逻辑地址由一个16比特的段选择符和一个32比特的偏移地址组成。同时,我们也知道,分段寄存器里只存储了段选择符。

       我们先接着第一节继续对段选择符进行分析。它的格式如下所示:

     Index:标记了GDT或LDT中段描述符的入口。由于段寄存器有8个字节长,它在GDT或LDT中的相对地址是这样来计算的:13个bit之长(如上图,比特3-15位)的index域值乘以8. 假设GDT位于0x00020000 (该值存放在gdtr控制寄存器中) 并且 段选择符的index域值为2,那么相应的段描述符的地址是这么来计算的:

     0x00020000 +(2 x8),0x00020010.

   TI: table indicator。TI=0,表示段描述符位于GDT中;TI=1,表示段描述符位于LDT中。

   RPL:Requestor Previlige Level请求者优先级。

    为了加快逻辑地址到线性地址的转换过程,80x86增加了一个不可编程的寄存器。

      每当一个段选择符被加载到分段寄存器中时,相应的段描述符也被从内存里加载到那个匹配的不可编程的CPU寄存器中。这样,逻辑地址的转换就不再需要访问主内存中的GDT和LDT,而只需要访问那个包含段描述符的不可编程的寄存器。只有在分段寄存器内容改变时,才需要访问LDT或GDT。

 

3.分段单元实现逻辑地址到线性地址的转换

      我们知道,内存管理单元(MMU)可通过一个叫做分段单元(segmentation unit)的硬件电路,将逻辑地址转换成线性地址;接着,通过一个叫做分页单元(paging unit)的电路,再将线性地址转换成物理地址。如下图所示:

          那么,这个分段单元是按照什么样的流程完成自己的职责所在呢?

             首先,它会检查段选择符的TI域,进而知道是哪个描述表存放了相应的段描述符。如果段描述符位于GDT,则分段单元从gdtr寄存器中读取GDT的线性基地址;否则,分段单元从ldtr读取LDT的线性基地址。

        其次,根据上一步得到的线性基地址和段选择符的index域,计算出段描述符的地址。计算方法可参考上节。

通过以上两步,我们就可以定位到我们需要的段描述符。

        最后,把逻辑地址的偏移与前面定位到的段描述符的线性地址BASE域相加,得到线性地址。这样,整个逻辑地址到线性地址的转换过程就成了

        地址转换的过程如下图所示:

注意,本文中的线性地址跟虚拟地址是一个概念。如有不懂,请参阅我的上一篇文章。

Smith先生翻译版权所有,如需转载,请注明出处:http://blog.csdn.net/acs713/article/details/7950622

Logo

更多推荐