当前位置: 首页 >> 开源操作系统 >> Linux内核的段式管理
 

Linux内核的段式管理

作者:      来源:zhuxizhi.cublog.cn     发表时间:2006-12-18     浏览次数:      字号:    

段式管理用以将逻辑地址转化为线性地址。一个逻辑地址由一个16位的段选择子和一个32位的偏移量组成。

1、段选择子和段寄存器
    为了快速的对段进行访问,i386提供了6个段寄存器以存放段选择子,分别为CS(代码段寄存器)、SS(栈段寄存器)、DS(全局和静态数据段寄存器)、ES(后三个均为任意数据段寄存器)、FSGS。此外,i386还提供了6个段描述符寄存器(对程序员不可见),用来缓存相应段寄存器所对应段的段描述符。段寄存器格式如下:

Index

TI

RPL

    其中,Index13位,为访问段描述符数组项的下标;TI只有1位,为0表示使用GDT1表示使用LDTRPL2位,用以表示当前进程的特权级别。
2、段描述符
    每个段的属性在内存中由一个8字节的段描述符表示,段描述符存放在全局描述符表(GDT)或者局部描述符表(LDT)中,其地址和体积分别保存在GDTRLDTR寄存器中。段描述符的结构如下:

Base24-Base31

G

D/B

L

AVL

Limit16-Limit19

P

DPL

S

Type

Base16-Base23

Base0-Base15

Limit0-Limit15

    其中,Base32位的段基(线性)地址;Limit20位的段长度;G只有1位,为0表示段长度以字节为单位,1表示段长度以4KB为单位;D/B只有1位,为0表示为16位段,1表示为32位段;L只有1位,未使用;AVL只有1位,供系统软件使用(Linux从未使用该位);P只有1位,表示该段内容是否在内存中(Linux从不将整个段替换出内存,故该位恒为1);DPL2位,表示访问该段所需要的特权级别;S只有1位,为0表示段为存放关键数据的系统段,1表示段为普通段;Type4位,定义了段类型和访问权限。
    在linux系统中,主要包括代码段描述符、数据段描述符(包含栈段)、任务状态段(TSSType字段值为911)描述符和局部描述符表(LDTType字段值为2)描述符四种段描述符。其中,前两者可以被包含在GDTLDT中,TSSDLDTD为系统关键段,仅能包含在GDT中。
3Linux内核中的分段
    出于效率和兼容性的考虑,Linux内核中对分段的支持有限,仅在i386结构有要求时才使用分段。
1)代码段和数据段
    在linux中,所有用户进程都使用相同的代码段(__USER_CS)和数据段(__USER_DS),所有的内核进程都使用相同的代码段(__KERNEL_CS)和数据段(__KERNEL_DS)。这四个段的段描述符主要字段如下:

Segment

Base

G

Limit

S

Type

DPL

D/B

P

__USER_CS

0x00000000

1

0xFFFFF

1

10

3

1

1

__USER_DS

0x00000000

1

0xFFFFF

1

2

3

1

1

__KERNEL_CS

0x00000000

1

0xFFFFF

1

10

0

1

1

__KERNEL_DS

0x00000000

1

0xFFFFF

1

2

0

1

1

    即,这四个段均为覆盖整个地址空间的32位普通段,仅有TypeDPL存在差异。在发生特权级变化时,内核会自动将由相应宏表示的段载入到段寄存器中。
2Linux中的GDT
    在linux中,每个处理器需要一个GDT。所有的GDT都保存在arch/i386/kernel/head.S文件中的cpu_gdt_table数组中,其地址和体积则保存在同一文件的cpu_gdt_descr数组中。GDT表共有32项,其中包含了18个段描述符和14个保留项。这18个段描述符如下:
段选择子为0x00null
段选择子为0x300x380x40的三个线程本地存储段(TLS#1-TLS#3),用以辅助多线程程序在本地存储局部数据;
段选择子为0x60__KERNEL_CS,段选择子为0x68__KERNEL_DS,段选择子为0x70__USER_CS,段选择子为0x78__USER_DS
段选择子为0x80的任务状态段(TSS),用以保存进程的状态,不同处理器的GDT中的TSS不同;
段选择子为0x88LDT
段选择子为0x900x980xA00xA80xB0的五个和Plug and PlayPnPBIOS服务相关的段;
段选择子为0xB80xC00xC8的三个和高级电源管理(APM)相关的段;
段选择子为0xF8的一个特殊的TSS,由内核用以处理“Double fault”异常。
3Linux中的LDT
    由于Linux的大多数用户进程都不使用LDT,其内核仅在arch/i386/kernel/traps.c文件中定义了一个五元素的数组default_ldt来保存被进程共享的LDT。其中,只有两个可被内核使用:用于iBCS可执行代码的调用门,和用于Solaris /x86可执行代码的调用门。
    此外,用户进程可以调用modify_ldt()系统调用来管理自身的LDT,但内核不会对其进行严格的管理。

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •