linux内核完全剖析之(1)——80x86保护模式

      寄存器的作用是协助处理器执行初始化和控制系统操作。

     处理器提供了4个内存管理寄存器(GDTR(全局描述符表寄存器),LDTR(局部描述符表寄存器),IDTR(中断描述符表寄存器),TR(任务寄存器)),用于指定分段内存管理所使用的系统表的基地址。他们都是段基址寄存器。

             1、GDTR(全局描述符表寄存器)用于存放全局描述符表GDT的32位线性基地址和16位表长度值。

             2、IDTR(中断描述符表寄存器)用于存放中断描述符表IDT的32位线性基地址和16位表长度值。

             3、LDTR(局部描述符表寄存器)用于存放局部描述符表LDT的32位线性基地址和16位表长度值。

             4、TR(任务寄存器)用于存放当前任务TSS(任务状态段)的16位段选择符,32位基地址,16位段长度和描述符属性值。

内存寻址的地址变换技术包括:分段寻址,分页寻址。

80x86为段部分提供了6个存放段选择符的段寄存器:CS(代码段(用于寻址代码段)),DS(数据段),ES,SS(堆栈段),FS,GS。

内存管理系统的两个关键部分:保护和地址变换。

从逻辑地址到物理地址的变换

linux内核完全剖析之(1)——80x86保护模式_第1张图片
分段机制提供了隔绝代码数据和堆栈区域的机制,因此多个程序或任务可以运行在同一个处理器上而不会相互干扰。
每一个分段可以用来存放代码、数据、堆栈或者存放系统数据结构。
分页机制位虚拟内存系统提供了实现机制,同时也可以提供多任务之间的隔离措施。
分段机制:
首先由程序提供逻辑地址,逻辑地址中包括段选择符和偏移量。段选择符中的标志位决定采用全局描述符表还是局部描述符表。描述符表中指明了段的大小,段基址,段类型等。段选择符中有12位地址(假定为n),则线性地址的计算方式如下:
线性地址=段基址+n*8B+偏移量。
linux内核完全剖析之(1)——80x86保护模式_第2张图片
分页机制:
不同的分段机制和分页机制可以任意的组合。分段机制必须有,分页机制可以不用。如果没有分页机制,线性地址=物理地址
分段机制在各种可变长度的内存区域上操作。分页机制对固定大小(一般为4K)的内存块进行操作。
分页机制把线性地址和物理地址都划分成页面。线性地址空间中的任何页面可以被映射到物理地址空间的页面。
分页机制把2^32线性地址空间分为2^20个页面,每个页面大小为2^12.。
线性地址允许被标注为无效的,而不是产生一个物理地址。导致线性地址无效的情况有(1)操作系统不支持的线性地址。(该情况必须被终止)(2)虚拟内存系统的页面在磁盘上而不是物理内存中(可从磁盘中加载到物理内存中)。
段的长度通常是存放代码或数据结构的长度,而页的长度是固定的,一个页面可能不能完全存储一个数据结构或代码,它允许一部分数据结构存储在物理内存中,另一部分存储在磁盘中,存储在磁盘中的可以再需要时再调用。
页表结构:
线性地址的高20位构成了2^20个物理地址数组,用于确定物理地址的基址,后12位给出了页面偏移量。
linux0.12内核将也表分为两级结构:页目录和页表。具有2^10个表项,他是用来索引二级目录中的2^10个二级目录的。所以一级目录中的表项和二级目录的表项是一一对应的。
linux内核完全剖析之(1)——80x86保护模式_第3张图片
目录页表总是存在于物理内存中,而二级页表可以在需要时再分配,而且允许分散在内存中的各个页面中。
保护机制:
在保护模式下,80x86提供了段级保护和页级保护。
段级保护包括段限长检查,段类型检查,特权级保护。
段限长检查:段描述符的段限长字段用于防止程序或过程寻址到段外的内存地址。
段类型检查:系统段描述符和门描述符用于管理任务以及异常和中断。当操作段选择符和段描述符时,系统会检查类型。
特权级保护:分为四级(0,1,2,3)数值越大特权越小。处理器可以处理三种特权级:CPL(当前特权级),DPL(描述符特权级),RPL(请求特权级)
CPL:是当前正在执行的任务或程序的特权级。通常CPL=当前代码段的CPL。如果在访问一致代码段时,CPL的值大于一致代码段的DPL时,可以访问该代码段。但CPL并不会修改为DPL的值。
DPL:描述符特权级,DPL是一个段或者门的特权级。被访问的段或门的类型不同时其含义也不同。在访问数据段时,DPL指出允许访问该数据的程序应具有比DPL特权高的特权。例:如果数据段的DPL为1,则代码的CPL位0或1.在访问非一致代码段时,CPL=DPL。访问调用门时与访问数据段的方式相同。访问任务状态段时访问规则与数据段相同。通过调用门访问一致和非一致代码段时,DPL指出程序应该具有的最小特权值。例如访问一致代码DPL位2,则程序的CPL的值最小为3.
RPL:请求特权级,如果程序的RPL的特权级大于CPL则RPL会覆盖CPL,反之亦然。即始终取特权值最大的(特权值最大值的是数值最大,比如RPL位2,CPL为3,则取3)。
数据段特权检查:在访问数据段时,段选择符要加到段寄存器中,在这之前要检查特权级,DPL数值大于或等于CPL|RPL时才会加载。
处理器检查CPL,DPL,RPL的规则:
当访问非一致代码段(同级别可访问)时,CPL=DPL。且RPL的数值要《=CPL。
当访问移植代码段时CPL的值》=DPL。且忽略对RPL的检查(只要CPL》=DPL,如果RPL《=CPL,则CPL起作用,如果RPL》=CPL,则RPL起作用,而RPL肯定》=DPL,所以可以忽略RPL值)。
 
门描述符可以提供不同特权级的代码段的受控访问,非一致代码段没有这样的功能,一致代码段只能提供低级别到高级别的访问。四种门描述:调用门,中断门,陷阱门,任务门。任务门用于任务之间的切换。陷阱门和中断门时调用门的特殊类。
CALL指令可以通过调用门把程序由特权级低的转到特权级高的(在非一致性代码段中)。而JMP和CALL在一致性代码段中可以把控制转移到更高级别的代码段中。
堆栈切换只发生在调用门中。即当调用门将控制转移到啊、更高级别特权的代码段中时,就会执行堆栈切换。目的是为了防止高特权级程序栈空间不足而引起的崩溃。每个任务最多定义四个栈,用以分别运行四个不同级别的应用程序代码。
页级保护:分页机制只识别两级权限(0,1,2级权限为超级用户,3级权限为普通用户)。超级用户对所有页面都是可读/可写/可执行。
linux内核完全剖析之(1)——80x86保护模式_第4张图片
页级保护机制是在分段机制发挥作用之后才起作用。段级和页级保护机制相当于串联电路,成为串行保护。如下图:
linux内核完全剖析之(1)——80x86保护模式_第5张图片

 

 

你可能感兴趣的:(linux内核完全剖析之(1)——80x86保护模式)