转载请注明来源:http://blog.csdn.net/imred/article/details/50659212
(本文为《深入理解Linux内核》笔记)
对于80x86处理器,我们要区分以下三种地址:
逻辑地址:由段地址和段内偏移两部分组成。
线性地址(虚拟地址):将逻辑地址进行解释得到的地址形式,它是一个32位无符号整数,值的范围为0x00000000到0xffffffff可对4GB的空间进行寻址。之所以又称为虚拟地址,是因为后来的虚拟存储技术,使得线性地址并不会直接对应到相应的物理地址,而要经过一定的映射,将线性地址转换为物理地址,为了与物理地址相对应,又将线性地址称为虚拟地址。
物理地址:对内存芯片进行寻址时的地址,进行寻址时CPU会将这个地址以电信号的形式发送给内存芯片进行寻址。
将逻辑地址转换为线性地址、将线性地址转换为物理地址都在内存管理单元(MMU)中进行;前者使用分段单元进行转换,后者使用分页单元进行转换。
在引入保护模式之前,分段单元进行地址转换时使用的是实模式。在实模式下,段地址直接存储在段寄存器中,偏移地址保存在一个地址寄存器中或直接使用一个立即数。将逻辑地址转换为线性地址很简单:线性地址=段地址*16+偏移地址(这个线性地址实际上也是物理地址)。
保护模式是从80286引入的,此时段地址并不会直接保存在段寄存器内,而是保存在内存中,段寄存器只是保存了一个索引,使用这个索引可以在内存中取出相应的段地址。得到段地址后再与段内地址偏移相加便得到线性地址。保护模式有两个重要的概念:段选择符和段描述符,我们来仔细的看一看这两个概念。
首先来看段选择符(Segment Selector),长度为16位,保存在段寄存器(cs,ds,ss,es,fs和gs)中。这个段选择符只是一个索引,但其中只有13位用作索引;还有一位用于指示段描述符是全局的还是局部的,这两类段描述符保存在不同的位置;另外两位用于指明CPU的当前特权级(Current Privilege Level),0为最高,3为最低,通常只有特权级0(ring 0)和特权级3(ring 3)被操作系统使用。段选择符格式如下:
然后来看段描述符(Segment Descriptor),长度为8字节(64位)。段描述符都放在段描述符表中,段选择符即指明了段描述符在段描述符表中的位置。
段描述符有两种:全局描述符表(GDT)和局部描述符表(LDT)。通常只定义一个GDT,而每一个进程都有自己的LDT。GDT在内存中的首址(32位)和大小(16位)存放在gdtr控制寄存器中,当前正被使用的LDT首址(32位)和大小(16位)放在ldtr控制寄存器中。
段描述符有以下字段:
Base:段的首址,不连续地存放在段描述符中,32位。
G:粒度标识,0=段大小以字节为单位,1=段大小以4K字节为单位。
Limit:段的大小,不连续地存放在段描述符中,20位。因此G=0时,段最大为1MB,G=1时,段最大为4GB。
S:系统标识,0=这是一个系统段,用于存放诸如LDT这类关键的数据结构,1=这是一个非系统段,用于存放普通应用程序的代码或数据。
Type:描述了段的类型和存储权限,4位。位0:A(Accessed)位,指示描述符是否已被访问,0=相应的段选择符不在段寄存器中,1=相应的段选择符在段寄存器中;位3:E(Executable)位,指明段是否可执行,0=段为数据段,1=段为代码段。当段为数据段时,位1:W(Write)位,指明段是否可写,0=数据段只读,1=数据段可读写;位2:ED(Extend Direction)位,指明段的扩展方向,0=向高位扩展,1=向低位扩展。当段为可执行段时,位1:R(Read)位,指明段是否可读,0=不可读,1=可读;位2:C(Conform)位,指明该段是否为一致代码段,0=非一致代码段,1=一致代码段。
DPL:描述符特权级(Descriptor Privilege Level)字段,用于限制对这个段的访问,它表示为访问这个段而要求的CPU最低的优先级,2位。DPL=0的段只有CPL=0时才能访问,DPL=3的段对CPL为任何值时都可以访问。
P:Segment-Present标识,0=当前段不在主存中,1=当前段在主存中。
D或B:称为D或B的标识,取决于是代码段还是数据段。D或B的含义在两种情况下稍微有些区别,但是如果段偏移量的地址是32位长,就基本上把它置为1,如果这个偏移量是16位长,它被清0(详见Intel相关手册)。
AVL标识:可由操作系统使用。
段描述符格式如下:
![]()
以上就是关于段选择符和段描述符的概念,下面来看分段单元如何使用它们来将逻辑地址转换成相应的线性地址。
由于一个段描述符是8字节长,因此一个段描述符在GDT或LDT内的相对地址是由段选择符的最高13位的值(即索引位)乘以8得到的。
首先,检查段选择符的TI字段,以决定段描述符保存在哪一个描述符表中。当段描述符在GDT中时,分段单元从gdtr寄存器中得到GDT的基址;当段描述符在LDT中时,分段单元从ldtr寄存器中得到LDT的基址。
然后,从段选择符的index字段计算段描述符的地址,index字段的值乘以8,这个结果与gdtr或ldtr寄存器中的内容相加。
最后,把逻辑地址的偏移量与段描述Base字段的值相加就得到了线性地址。
以上就是80x86处理器在保护模式下的分段机制的大致原理。
转载请注明来源:http://blog.csdn.net/imred/article/details/50659212