《intel开发手册卷3》读书笔记2

        IA-32架构的内存管理分为两个部分:分段和分页。分段提供了一种隔离每个进程
或者任务代码、数据和栈模块的机制,保证多个进程或者任务能够在同一个处理器上运
行而不会互相干扰。分页机制实现了传统请求调页的虚拟内存系统,在这种系统中,
程序的执行环境块 按需要 被映射到物理内存中。分页机制同样可以用来隔离多个任务。
在保护模式下,分段机制是必须的,分页机制则是可选的。 注意:没有一个标志位可
用来关闭分段功能。
1、分段结构
         分段将处理器可寻址空间(即线性地址空间)分为较小的受保护的地址空间:段。段可以被用来装载一个程序的代码、数据或者堆栈,亦或装载系统的数据结构(如 TSS、LDT 等)。当处理器上运行多个进程时,可以为每个进程分配属于它自己的段集合。处理器会强制规定这些段的边界,以确保不会因为一个进程对属于另一个程序的段进行误写而互相干扰执行。分段机制也可以对段进行分类,确保操作限于某种类型的段。
        系统中所有的段都包含在处理器的线性地址空间内。 有逻辑地址(也称为远指针)才能确定一个字节在一个特定段中的位置。逻辑地址由段选择子和偏移组成。段选择子是一个段的唯一标识。除此以外,它还是描述符表(比如全局描述符表 GDT)中的偏移,供访问一个叫做段描述符的数据结构之用。每个段有一个段描述符,段描述符描述段的大小、访问权限、段的优先权、段的类型以及段的第一个字节在线性地址空间的位置(也称为段基地址)等。通过将逻辑地址中的偏移部分加上段基地址就可以确定这个地址在段中的字节位置。 段基地址加偏移就构成了处理器线性地址空间的线性地址
        如果系统没有采用分页机制,线性地址空间就直接映射到物理地址空间。在多任务计算系统中,通常会定义一个比实际物理内存空间大的多的线性地址空间,因此需要使用一些方法来“虚拟化”线性地址空间。 线性地址空间的虚拟化由处理器的分页机制来完成。 
         分页机制支持虚拟内存环境,通过较小的物理内存(RAM 和 ROM)以及一些磁盘存
储空间来模拟一个很大的线性地址空间
。使用分页机制时,每个段被分成很多页(通常一个页的大小为 4KB),这些页或者在物理内存中,或者在磁盘上。 操作系统会维护一张页目录表和一组页表来记住这些页。当一个进程/任务试图访问线性地址空间的一个地址时,处理器通过页目录表和页表将线性地址转换成物理地址,然后对相应的物理地址执行要求的操作(读或写)。 如果被访问的页不在当前的物理内存中,处理器会中断这个进程的执行(产生一个缺页异常)。之后,操作系统或者管理程序会从磁盘上读取这个页到内存中,接着执行这个程序。 
1.1多段模型
         多段模型充分利用分段机制,提供对代码、数据结构、任务或者程序的硬件强制保护。在这里,每个进程(或者任务)都分配有自己的段描述符和相应的段。段可以完全归它们所分配的程序独占,也可以供其它进程共享。对所有段的访问和对运行在系统中的每个程序执行环境的访问都受硬件控制。
         访问检查机制不仅可以禁止对超过段界限的地址进行寻址,也可以禁止对特定段执行非法操作。比如,因为代码段被指定为只读的,所以用硬件来防止对代码段写入数据。段的访问权限信息也可以被用来建立保护级别。 保护级别可以用来防止操作系统的例程被未授权的应用进程访问
1.2、逻辑地址和线性地址
        在保护模式的系统架构中,处理器分两步进行地址转换以得到物理地址:逻辑地址转换和线性地址空间分页。
        即使最小程度的使用段机制,处理器地址空间内的每一个字节都是通过逻辑地址访问的。 一个逻辑地址由一个 16 位的段选择子和一个 32 位的偏移组成。段选择子确定字节位于哪个段,偏移确定字节在段中相对于段基地址的位置。
        处理器将逻辑地址转换为线性地址。线性地址是处理器线性地址空间内的 32 位的地址。与物理地址一样,线性地址是平坦的(不分段的),空间大小为  2^{32} 字节,从地址 0 到FFFFFFFFH。 线性地址空间包含了所有的段和为系统定义的各种系统表
        处理器通过如下几个步骤将逻辑地址转换为线性地址: 
                1. 使用段选择子中的偏移,找到 GDT 或者 LDT 中相应的段描述符,得到段信息并把它读到处理器中。(仅当一个新的段选择子被读入段寄存器时才执行这一步。) 
                2.检查段描述符中的访问权限和段的地址范围,确保段是可访问的且偏移在段界限范围内。 
                3.将段描述符中的段基址与偏移相加构成线性地址。 
         如果没有使用分页,处理器直接将线性地址映射为物理地址(也就是说线性地址直接送到处理器的地址总线上)。如果在线性地址空间启用了分页机制,就需要再进行一次地址转换,将线性地址转换为物理地址
1.3、段选择子
        
         段选择子是一个 16 位的段的标识码,它并不直接指向段,而是指向定义段的段描述符。段选择子包含以下项目:
        
        索引 (第 3 位到第 15 位)。选择 GDT 或 LDT 中 8192 个描述符中的某一个。处理器将索引值乘以 8(段描述符的字节数),然后加上 GDT或 LDT 的基地址(分别在 GDTR 或者 LDTR 寄存器中)。
        表指示标记(TI) 第 2 位)。确定使用哪一个描述符表: 将这个标记置 0,则表示用 GDT。将这个标记置 1,则表示用 LDT。        
        请求的特权级(RPL)。 确定选择子的特权级,特权级的范围是 0 到3,0 为最高特权级。有关 RPL 与当前任务的 CPL 之间的关系以及段选择子所指的描述符的描述符特权级(DPL)的描述。
        G DT 的第一项是不用的。指向 GDT 第一项的段选择子(即选择子中的索引为 0,表指示标记 TI 置为 0)被视为“空段选择子”。当段寄存器(不是 CS 或 SS 寄存器)装载一个空选择子时,处理器并不产生异常。但是,当用装有空选择子的段寄存器来访问内存时,处理器则会产生异常。空选择子可以用来初始化未使用的段寄存器。对 CS 或者 SS 装载一个空选择子会产生一个一般保护异常(#GP)。 
         段选择子作为指针变量的一部分对应用程序而言是可见的,但是其值由连接编译器或者连接装载器程序赋予或者更改,而不是应用程序。 
1.3、段寄存器
        为了减少地址转换的时间和编码复杂度,处理器提供了6个段寄存器来保存段选择子。每个段寄存器都支持某个特定类型的内存寻址(代码、堆栈、数据等等)。 实际上,对任何程序的执行而言,至少要将代码段寄存器(CS),数据段寄存器(DS)和堆栈段寄存器(SS)赋予有效的段选择子。此外,处理器还提供了另外3个数据段寄存器(ES、FS和GS)供当前执行程序(任务)增加数据段时使用。段的段选择子必须被装载到某一个段寄存器中才可以让程序访问段。 因此,尽管系统可以定义数千个段,但只有6个段是可以被直接使用的。其它段只有在程序执行期间把它们的段选择子装入这些段寄存器中才可以被使用
        每个段寄存器都由“可见”部分和“不可见”部分组成。(有时,不可见部分也被称为“描述符高速缓存”或者“影子寄存器”)。 当段选择子被装载到一个段寄存器的可见部分时,处理器也把段选择子指向的段描述符中的段基地址、段界限和访问权限等信息装载进来。段寄存器保存的信息(可见或不可见的)使得处理器在进行地址转换时,不需要花费额外的总线周期来从段描述符中获取段基地址和段界限。在允许多个处理器访问同一个描述符表的系统中,当描述符表被改变后,软件应该重新载入段寄存器。
        有两种载入段寄存器的指令:
                1.直接载入指令,如MOV、POP、LDS、LES、LSS、LGS和LFS。这些指令明确指定了相应的寄存器。
                2.隐含的载入指令,如远指针型的CALL、JMP、RET指令,SYSENTER和SYSEXIT指令,还有IRET、INTn、INTO和INT3指令。伴随这些指令的操作,改变了CS寄存器(有时也包括其它段寄存器)的内容。
                MOV指令也可以用于将一个段寄存器的可见部分保存到一个通用寄存器中。
1.4、段描述符
         段描述符是GDT或LDT中的一个数据结构,它为处理器提供诸如段基地址、段大小、访问权限及状态等信息。段描述符主要是由编译器、连接器、装载器或者操作系统/管理程序设立的,而不是由应用程序产生的
段描述符的标志和域如下:
        1)段界限域:指定段的大小。处理器将两个段界限域合在一起组成一个20位的段界限值。根据G标志位(粒度)的不同设置,处理器按两种不同的方式解释段界限: 如果粒度标志位为0,则段大小可以从1字节到1M字节,段长增量单位为字节;如果粒度标志位为1,则段大小可以从4K字节到4G字节,段长增量单位为4K字节
        根据段是“向上扩展段”还是“向下扩展段”,处理器对段界限有两种不同的处理方式 。在向上扩展段中,逻辑地址偏移的范围从0到段界限。超过段界限的偏移会导致一般保护异常(#GP)。在向下扩展段,段界限的作用正好相反;偏移的范围从段界限到FFFFFFFFH或者FFFFH,这由标志位B的值决定。小于段界限的偏移也会导致一般保护异常。 减少向下扩展段的段界限将会在段地址空间的底部而不是顶部为该段分配新的内存空间
        2)基址域:确定段的第一个字节(字节0)在4GB线性地址空间中的位置。 处理器将3个基地址域组合在一起构成了一个32位地址值。段基地址应当是16字节边界对齐的。16字节边界对齐不是必须的,但这种段边界的对齐能够使程序把代码和数据对其到16字节边界上而最大化其性能。
        3)类型域: 指明段或者门的类型,确定段的访问权限和增长方向。如何解释这个域,取决于该描述符是应用程序描述符(代码或数据)还是系统描述符。代码段、数据段和系统段对类型域有不同的编码。
        4)S标志(描述符类型): 确定段描述符是系统描述符(S 标记为 0)或者代码、数据段描述符S 标记为 1)
        5)DPL(描述符特权)域:指明段的特权级。特权级从0到3,0为最高特权级。DPL用来控制对段的访问。
        6)P标志(段存在): 指明段当前是否在内存中(1表示在内存中,0表示不在)。当指向段描述符的段选择子被装进段寄存器时,如果这个标志为0,处理器会产生段不存在异常(#NP)。内存管理软件可以通过这个标志,来控制在某个特定时间有哪些段是真正的被载入物理内存的。这是除分页之外的另一个虚拟内存控制机制。
        7)D/B(默认操作数大小/默认栈指针大小和上限)标志:根据段描述符所指的是可执行代码段、向下扩展的数据段还是堆栈段,这个标志有不同的功能。(对32位的代码和数据段,这个标志总是被置为1,而16位的代码和数据段,这个标志总是被置为0)。这个标志按照S标志类型的不同代表的含义也不同:
                7)A、可执行代码段:这个标志被称为 D 标志,它指明段中指令的有效地址和操作符的默认位数。如果该标志为 1,则默认 32 位的地址,32位或者8位的操作符;若为0,则默认16位的地址,16位或者8位的操作符。指令前缀66H可以指定操作符的长度而不使用缺省长度。前缀67H可用来指定地址值的长度。
                7)B、堆栈段(SS寄存器所指的数据段):这个标志被称为B(大的)标志,它为隐含的栈操作(如push、pop和call)确定栈指针的大小。如果该标志为1 ,则使用32位的栈指针,栈指针放在32位的ESP寄存器中;若该标志为0,则使用16位的栈指针,栈指针存放在SP寄存器中。如果堆栈段为一个向下扩展的数据段(见下一段的说明),则B标志还确定堆栈段的地址上界。
                7)C、向下扩展的数据段:这个标志称为B标志,确定段的地址上界。如果该标志为1,则段地址上界为FFFFFFFFH(4GB);若该标志为0,则段地址上界为FFFFH(64KB)。
        8)G(粒度)标志: 确定段界限扩展的增量。当G标志为0,则段界限以字节为单位扩展;G标志为1,则段界限以4KB为单位扩展。(这个标志不影响段基址的粒度,段基址的粒度永远是字节。)如果G标志为1,那么当检测偏移是否超越段界限时,不用测试偏移的低12位。例如,如果G标志为1,0段界限意味着有效偏移为从0到4095。
        9)可用以及保留位:段描述符的第二个双字的第20位可以被系统软件使用,第21位被保留,并且应该设置为0。
1.4、代码段和数据段
        当段描述符中的S标志(描述符类型)为1时,描述符为代码段描述符或者数据段描述符。 类型域的最高位(段描述符的第二个双字的第11位)将决定该描述符为数据段描述符(为0)还是代码段描述符(为1)
        对于数据段而言,描述符的类型域的低3位(第8、9、10位)被解释为访问控制(A)、是否可写(W)、扩展方向(E)。
         堆栈段必须是可读写的数据段。将一个不可写的数据段的选择子置入SS寄存器会导致一般保护异常(#GP)。如果堆栈段的大小需要动态变化,可以将其置为向下扩展数据段(扩展方向标志为1)。这里,动态改变段界限将导致栈空间朝着栈底部空间扩展。如果段的长度保持不变,堆栈段可以是向上扩展的,也可以是向下扩展的。对于代码段而言,类型域的低3位被解释为访问位(A)、可读位(R)、一致位(C)。
        访问位表示自最后一次被操作系统清零后,段是否被访问过。每当处理器将段的段选择子置入段寄存器时,就将访问位置为1。该位一直保持为1直到被显式清零。该位可以用于虚拟内存管理和调试。代码段可以是一致性的,也可以是不一致性的。转入一个特权级更高的一致性段的进程可以在当前特权级继续执行下去。除非使用了调用门或者任务门,否则,转入一个不同特权级的非一致性段将使处理器产生一个“一般保护异常”(#GP)。不访问受保护程序的系统程序和某些类型的异常处理程序(比如除法错或者溢出)可以被载入一致性的代码段。不能被特权级更低的程序和过程访问的程序应该被载入非一致性的代码段。
         无论目标段是否为一致性代码段,进程都不能因为call或jump而转入一个特权级较低(特权值较大)的代码段执行。试图进行这样的执行转换将导致一个一般保护异常(#GP)。
         所有的数据段都是非一致性的,这就意味着数据段不能被更低特权级的进程访问(特权级数值较大的执行代码)。然而,和代码段不同,数据段可以被更高优先级的程序或者过程(特权级数值较小的执行代码)访问,不需要使用特别的访问门。
1.5、系统描述符
        当段描述符的S标志(描述符类型)为0,则描述符为系统描述符。处理器可以识别以下类型的系统描述符:局部描述符表(LDT)段描述符、任务状态段(TSS)描述符、调用门描述符、中断门描述符、陷阱门描述、任务门描述符。这些描述符又可以分为两类:系统段描述符和门描述符。系统段描述符指向系统段(LDT和TSS段)。 门描述符它们自身就是“门”,它们或者持有指向放置在代码段中的过程入口点的指针,或者持有TSS(任务门)的段选择子
1.6、段描述符表
        段描述符表是一个段描述符的数组。段描述符表的长度是可变的,最多可以包含8192(213)个8字节的描述符。有两种描述符表:全局描述符表(GDT)局部描述符表(LDT)。
        系统必须定义一个GDT,以供所有的进程或者任务使用。也可以定义一个或者多个LDT。比如,可以为每个正在运行的任务定义一个LDT,也可以让所有的任务共享一个LDT。 GDT本身不是一个段,而是线性地址空间中的一个数据结构。GDT的线性基地址和界限必须被装入GDTR寄存器。GDT的基地址应当按照8字节方式对齐,这样可以获得最好的处理器性能。GDT的界限是按字节计算的。在段中,段界限加上段基地址就可以得到段最后一个字节的有效地址。0界限值表示只有一个有效的字节。因为段描述符总是8字节长,GDT的界限应该总是8的整数倍减1(即8N-1)。
         处理器并不使用GDT中的第一个描述符。当指向这个NULL描述符的段选择子被装入数据段寄存器(DS、ES、FS或者GS)时,处理器并不产生异常。但是如果使用这个NULL描述符来访问内存,处理器就会产生一个一般保护异常(#GP)。使用这个指向NULL描述符的段选择子来初始化段寄存器,这样可以确保在不经意引用未使用的段寄存器时,处理器能产生一个异常。
         LDT位于类型为LDT的系统段内。GDT必须包含一个指向LDT段的段描述符。如果系统支持多个LDT,那么每个LDT段都要有一个段选择子,都要在GDT中有一个段描述符。LDT的段描述符可以位于GDT中的任何地方。 LDT是通过它的段选择子来访问的。为了避免在访问LDT时进行地址翻译,LDT的段选择子、线性基地址、段界限和访问权限都放在LDTR寄存器中
2、分页结构

        当系统运行在保护模式下时,IA-32架构允许将线性地址直接映射到一个大的物理空间(比如4GB的RAM)或者间接的(使用分页)映射到一个较小的物理内存和磁盘存储空间中。后一种映射线性地址空间的方法通常被称作虚拟内存或者请求调页虚拟内存。当使用分页时,处理器将线性地址空间划分成固定尺寸的页(4KB、2MB或者4MB),这些页可以被映射到物理内存或者磁盘存储空间。当一个程序(或者任务)引用内存中的一个逻辑地址时,处理器首先将它转换为线性地址,然后使用分页机制将线性地址转换为相应的物理地址。如果包含线性地址的页目前不在内存中,处理器产生一个页故障异常(#PF)。页故障异常处理程序的典型的做法就是指导操作系统或者管理程序将相应的页从磁盘上调入内存(在这个过程当中可能有另外一个页被调出内存存放到磁盘上)。页被调入内存后,就从异常处理程序返回,重新执行导致页故障异常的指令。处理器用来映射线性地址到物理地址的信息和产生页故障异常(如有必要)的信息存放在页目录表和页表中,页目录表和页表都存放在内存中。分页不同于分段,分页使用固定大小的页。与段不同,页有固定的尺寸,段通常与它所保存的代码或者数据结构的大小一样。如果只使用分段进行地址转换,则一个数据结构必须全部保存在物理内存中。如果启用了分页,一个数据结构可以部分在内存中,部分在磁盘中

        分页由处理器的控制寄存器的3个标志来控制:PG(分页)标志:CR0寄存器的第31位(从Intel386处理器开始的所有Intel处理器都有这个标志)。PSE(页尺寸扩展)标志:CR4寄存器的第4位(Pentium和PentiumPro处理器引入的)。PAE(物理地址扩展)标志:CR4寄存器的第5位(PentiumPro处理器引入的)。

        PG标志启用页转换机制。通常操作系统或者管理程序在处理器初始化的时候设置这个标志。如果处理器的页转换机制被用来实现请求调页虚拟存储系统,或者操作系统可以在虚拟8086模式下运行多个进程(或者任务),那么PG标志必须被设置。PSE标志启用更大尺寸的页:4MB的页或者2MB的页(当PAE标志置1时)当PSE标志被清零的时候,则使用通常的4KB页。PAE标志提供了将内存地址扩展到36位的一种方法。仅当开启分页机制后才可以使用物理地址扩展。它依赖和页目录表、页表一起使用的页目录指针表来寻址超过FFFFFFFFH的地址。

2.1、页表和页目录表

        当启用分页机制时,处理器用来进行线性地址到物理地址转换的信息包含在下列4个数据结构中:        

                页目录表——一个由32位页目录表项(PDE)组成的数组,放置在一个4KB的页中。一张页目录表最多包含1024个页目录表项。

                页表——一个由32位页表项(PTE)组成的数组,它存放于一个4KB的页中。一张页表最多包含1024个页表项。(2MB或者4MB的页不使用页表,它们直接从一个或者多个页目录表项映射出来。)

                页——一个4KB、2MB或者4MB的平坦地址空间。

                页目录指针表——由4个64位的项组成的数组,每一项都指向一个页目录表。仅当启用物理地址扩展时才使用这个数据结构。每个页目录表项都包含了一个PS(页尺寸)标志,这个标志指明该页目录表项是指向一张页表(其每个表项指向一个4KB的页)(PS置为0),还是直接指向一个4MB(PSE和PS置为1)或者2MB的页(PAE和PS为1)。

        每个分页结构条目都包含一个物理地址,该地址要么是另一个分页结构的地址,要么是页面帧的地址。在前一种情况下,条目被称为引用其他分页结构;在后一种情况下,条目被称为映射页面。用于任何转换的第一个分页结构位于 CR3 中的物理地址1。线性地址的转换采用以下迭代过程。线性地址的一部分(最初为最高位)选择分页结构中的一个条目(最初使用 CR3 定位)。如果该条目引用了另一个分页结构,则继续使用该分页结构和刚才使用的线性地址的下一部分。如果条目映射的是一个页面,则流程结束:条目中的物理地址是页面帧的物理地址,线性地址的剩余较低部分是页面偏移量。

2.2、线性地址转换(4KB页面)

        下图展示了映射线性地址到4KB的页时的页目录表和页表的层次结构。页目录表项指向页表,页表项指向物理内存中的页。这种分页的方法可以用来寻址2^{20}张页,覆盖2^{32}个字节(4GB)的线性地址空间。

        为了选择不同的表的项,线性地址被分为3个部分:1)页目录表项——第22位到第31位,作为表项在页目录表中的偏移。该表项提供所指页表的物理基地址。2)页表项——第12位到第21位,作为表项在所选页表中的偏移。该表项提供所选物理内存页的物理基地址。3)页偏移——第0位到第11位,提供地址在所选物理页中的偏移。内存管理软件可以让所有的进程和任务使用一个页目录表,也可以使每个任务使用一个页目录表,或者两种方法联合使用。

 2.3、线性地址转换(4MB页)

        下图显示了如何使用页目录表来映射线性地址到4MB页。页目录表的项指向物理内存中的4MB页。这种分页方法可以将多达1024个页映射到4GB的线性地址空间:

        通过设置控制寄存器CR4中的PSE标志和页目录表项中的页尺寸(PS)标志来启用4MB页。这两个标志都置1时,则线性地址被分为两个部分:1)页目录表项——第22位到第31位,提供目录项在页目录表中的偏移。目录项提供4MB页的物理基地址。2)页偏移——第0位到第21位,提供物理地址在页中的偏移。

        当启用或者禁用大的页尺寸时,在设置或者清零控制寄存器CR4的PSE标志以后,TLB必须被刷新。否则可能由于处理器使用了存在TLB中的过期的页转换信息而进行了错误的页转换。

        当CR4中的PSE标志置1时,则可以通过同一个页目录表来访问4MB页和4KB页的页表。如果PSE标志被清零,就只能访问4KB页的页表(无论页目录表项中PS标志如何设置)。混用4KB页和4MB页的典型例子是将操作系统或者管理程序内核放在大尺寸的页中来减少TLB命中率不高,从而整体上提高系统性能。处理器在不同的TLB中维护4MB页项和4KB页项。因此,将频繁使用的代码,比如内核,放在大尺寸的页中,从而为应用进程和任务留出了4KB页的TLB项。   

2.4、页目录表基地址

             当前页目录表的物理地址存放在CR3寄存器中(也称为页目录基址寄存器PDBR)如果启用了分页,装载PDBR必须作为处理器初始化过程的一部分(在启用分页之前)。之后,可以通过使用MOV指令装载一个新值到CR3来显式地改变PDBR的值,或者在任务切换时隐式地改变它。在PDBR中没有为页目录表而设的存在标志。当一个任务被挂起时,与之相关的页目录表也许不在内存(被请求调出物理内存)。但是操作系统要确保,在一个任务被调度运行之前,该任务的TSS中的PDBR映像所指的页目录表必须已经在内存中。只要任务还是处于活动状态,页目录表就必须保留在内存中

   分页内容太多了,懒得抄了

2.5、TLB

        应用程序和一般任务(特权级大于0)是无法访问TLB的。也就是说,应用程序不能使TLB失效。只有操作系统和特权级为0的管理程序可以使TLB失效或者让选定的TLB项失效。每当一个页目录表项或者页表项有变化时(包括“存在”标志被设置为0),操作系统都要立即将TLB中的相应项变为无效,这样,当下次引用这个项的时候,可以更新它。每当装载CR3寄存器时,所有的(非全局的)TLB都自动失效(除非某个页或者页表项的G标志被置位)。

3、特权级

        处理器使用特权级来阻止较低特权级的进程或任务访问特权级较高的段。当处理器检测到一个特权违例时,就会产生一个一般保护异常(#GP)。为了进行代码段和数据段之间的特权级检验,处理器识别以下三种类型的特权级:

        当前特权级(CPL):CPL是当前执行程序或任务的特权级。它存在CS段寄存器和SS段寄存器的第0位和第1位中。一般地,CPL与当前指令所在代码段的特权级相等。当进程的控制流程转到一个不同特权级的代码段时,处理器就改变CPL。当访问一致性代码段时,对CPL的处理会略有不同。一致性代码段可以被任何数值上等于或者大于(特权较低)本一致性代码段DPL的代码访问。同样,当处理器访问一个与CPL特权级不一样的一致性代码段时,不改变CPL。

        描述符特权级(DPL)。DPL是段或门的特权级。它存储在段或门的描述符的DPL域中。一旦当前执行的代码段试图访问一个段或门时,处理器会将那个段或门的DPL与CPL以及那个段或门的选择子的RPL进行比较。根据所访问的段或门的类型,对DPL的解释也会不一样:

                1)数据段:DPL指明访问这个段的进程或任务的特权级可以具有的最大数值。比如,如果某个数据段的DPL是1,只有运行在CPL为0或1的进程才可以访问它。

                2)非一致性代码段(不使用调用门):DPL指明访问这个段的进程或任务应该具有的特权级。比如,某个非一致性代码段的DPL为0,那么只有CPL为0的进程才能访问它。

                3)调用门:DPL指明能够访问这个调用门的当前进程或者任务的特权级应该具有的最大数值。(这个访问规则同样适用数据段。)

                4)通过调用门访问的一致性代码段和非一致性代码段:DPL指明能访问这个段的进程或任务的特权级的最低数值。比如,一个一致性代码段的DPL为2,那么CPL为0或1的进程就不能访问它。

                5)请求特权级(RPL):RPL是赋给段选择子的取代性特权级,存储在段选择子的第0位和第1位处理器检验RPL的同时也检验CPL来决定对段的访问是否被允许。即使请求访问的进程或任务有足够的特权去访问一个段,但是,如果RPL的特权级不够,访问会被拒绝。也就是说,如果这个段选择子的RPL在数值上大于CPL,RPL就取代CPL,反之亦然。RPL可用来确保特权代码不代表应用程序去访问的一个段,除非这个应用程序本身有这个段的访问特权。

        特权级检验是在段描述符的段选择子被装入段寄存器时进行的。用于数据访问的检验不同于用于代码段的进程控制转移的检验。

        为了访问数据段中的操作数,就必须将该数据段的段选择子装入数据段寄存器(DS、ES、FS或GS)或者堆栈段寄存器(SS)。(可以用MOV、POP、LDS、LES、LFS、LGS和LSS等指令装载段寄存器。)处理器将段选择子装入段寄存器之前,通过比较当前运行程序或任务的特权级(CPL)、段选择子的RPL和段描述符的DPL来进行特权级检验。如果DPL在数值上大于或者等于CPL和RPL,则处理器将段选择子装入段寄存器。否则,处理器会产生一个一般保护异常,不装载段寄存器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值