Linux内核学习之分段机制

这里讲的分段指的保护模式(protected mode)下的段机制。与保护模式相对的一个概念是实模式(real mode),实模式的地址由“段基址:偏移量”组成,段基址是个16位的寄存器(CS,DS等),这样显然限制了系统的寻址空间。保护模式的地址由“段选择子+偏移量组成”,段选择子(Segment Selector)仍然由16位寄存器(CS,DS等)指定,但是其意义也不再是段基址,而是指定了一个下标,用于从描述符表(X86把所有的段信息都存在这个表中)中提取对应的段信息。 

段选择子格式:高12位作为下标从段描述符表选择对应段信息,第2位指示从哪个描述符表寻找(TI=0是取GDT),在X86中共有两个,一个是全局描述符表GDT(Global Descriptor Table),另一个是局部描述符表LDT(Local Descriptor Table),低2位用于指示优先级RPL(Request Privilege Level)。X86共有4中优先级(也叫4个ring),不过linux仅仅使用0和3。

段描述符格式:段描述符中的BASE(32位)指定了该段的基址,LIMIT(26位)指定了段的范围,具体数值要根据G Bit来看,因为给定的是一个“粒度”,相当于一个单位,一般情况下是4K,所以总共就是2^26 * 4K = 2 ^ 32。另外TYPE指明该段的属性,比如是否代码、可执行等,而DPL是与优先级相关的属性。

Linux内核学习之分段机制

 

    分段机制(逻辑地址 -- 线性地址)

Linux内核学习之分段机制

 

Linux对分段机制的应用

    Linux对段机制的应用效果是等价于几乎绕过了段基址。在Linux中仅有4个段,用户代码段、数据段和内核代码段、数据段。

Segment   Base   G   Limit   S   Type   DPL   D/B   P  
user code   0x00000000   1   0xfffff   1   10   3   1   1  
user data   0x00000000   1   0xfffff   1   2   3   1   1  
kernel code   0x00000000   1   0xfffff   1   10   0   1   1  
kernel data   0x00000000   1   0xfffff   1   2   0   1   1  

不难看到,由于Base都为0,经分段机制后“线性地址=逻辑地址”,并且G=1(4K粒度)Limit=2^20,因此最大寻址空间为2^32。用户层与内核层描述符之间的区别在于DPL。

上述四个描述符都在统一放在GDT中,事实上Linux对LDT也是没怎么使用。GDT中内容如下:

Linux内核学习之分段机制

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzyggz.html