RPL是段选择子里面的bit 0和bit 1位组合所得的值,但这里要首先搞清楚什么是段选择子,根据Intel 的文件(IA-32 IntelR Architecture Software Developer's Manual, Volume 3System Programming Guide)它是一个16Bit identifier (原文:A segment selector is a 16-bit identifier for a segment). 但 identifier 又是什么. identifier 可以是一个变数的名字( An identifier is a name for variables), 简单的说它可以就是一般意义的变数. 这里 16-bit identifier for a segment 可以就是一个一般意义的16bit变数但同时要求对它的值解释的时候必须跟据Intel定下的规则---也就是bit 0和bit 1位的组合值就是RPL等等… 因此在程序里如果有需要的话你可以声明一个或者多个变数来代表这些段选择子,这样的话你的程序在某一时刻就可以有很多段选择子,当然有那么多段选择子就有 那么多RPL.可以这样说程序有多少个是RPL是你怎样看待你自己声明的变数. |
程序的CPL(CS.RPL)是CS register 里bit 0和bit 1 位组合所得的值.在某一时刻就只有这个值唯一的代表程序的CPL.

而DPL是段描述符中的特权级, 它的本意是用来代表它所描述的段的特权级. 一个程序可以使用很多段(Data,Code,Stack)也可以只用一个code段等.在正常的情况下当程序的环境建立好后,段描述符都不需要改变 -----当然DPL也不需要改变.

一、对数据段和堆栈段访问时的特权级控制:

要求访问数据段或堆栈段的程序的CPL≤待访问的数据段或堆栈段的DPL,同时选择子的RPL≤待访问的数据段或堆栈段的DPL,即程序访问数据段或堆栈段要遵循一个 准则:只有相同或更高特权级的代码才能访问相应的数据段。这里,RPL可能会削弱CPL的作用,访问数据段或堆栈段时,默认用CPU和RPL中的最小特权 级去访问数据段,所以max {CPL, RPL} ≤ DPL,否则访问失败。

二、对代码段访问的特权级控制(代码执行权的特权转移):

让我们先来记一些“定律”
所有的程序转跳,CPU 都不会把段选择子的RPL赋给转跳后程序的CS.RPL. .

转跳后程序的CPL(CS.RPL)只会有下面的俩种可能
转跳后程序的CPL(CS.RPL) = 转跳前程序的CPL(CS.RPL) 

转跳后程序的CPL(CS.RPL) = 转跳后程序的CodeDescriptor.DPL

以 Call 为例(只能跳到等于当前特权级或比当前特权级更高的段):
怎样决定这两种选择,这就要首先知道转跳后程序的段是一致代码段还是非一致代码段.其实也很简单,规则如下:
如果能成功转跳到一致代码段, 转跳后程序的CPL(CS.RPL) = 转跳前程序的CPL(CS.RPL),(转跳后程序的CPL继承了转跳前程序的CPL)
如果能成功转跳到非一致代码段, 转跳后程序的CPL(CS.RPL) =转跳后程序的Descriptor.DPL。(转跳后程序的CPL变成了该代码段的特权级.我在前面提到DPL是 段描述符中的特权级, 它的本意是用来代表它所描述的段的特权级)怎样才能成功转跳啦?

这里有四个重要的概念

1).段的保护观念是高特权级不找低特权级办事,低特权级找高特权级帮忙,相同的一定没问题.(这样想逻辑是没错,事实对不对就不知道.)也就是县长不找 乡长,乡长不求农民,反过来农民求乡长,乡长找县长.这个概念是最重要的。
2) 一致代码段的意义: 让客人很方便的利用主人(一致代码段)的东西为自己办事.但客人这身份没有改变NewCS.RPL=OldCS.RPL所以只能帮自己办事。比方说乡长有 一头牛,农民可以借来帮自己种田,但不能种别人的田.但是如果你是乡长当然可以种乡里所有的田。
3) 非一致代码段的意义:主人(非一致代码段)可以帮客人但一定是用自己的身份NewCS.RPL= DestinationDescriptorCode.DPL这里可能有安全的问题, 搞不好很容易农民变县长。主人太顽固了一定要坚持自己的身份,有什么方法变通一下,来个妥协好不好。好的,它就是RPL的用处。
4) RPL: 它让程序有需要的时候可以表示一个特权级更低的身份Max(RPL,CPL)而不会失去本身的特权级CPL(CS.RPL),有需要的时候是指要检查身份 的时候。事实上RPL跟段本身的特权级DPL和当前特权级CPL没有什么关系,因为RPL的值在成功转跳后并不赋给转跳后的CS.RPL。
还是要问怎样才能成功转跳啦?这里分两种情况:

普通转跳(没有经过Gate 这东西):即JMP或Call后跟着48位全指针(16位段选择子+32位地址偏移),且其中的段选择子指向代码段描述符,这样的跳转称为直接(普通)跳 转。普通跳转不能使特权级发生跃迁,即不会引起CPL的变化,看下面的详细描述:

目标是一致代码段:
要求:CPL(CS.RPL)>=DestinationDescriptorCode.DPL ,其他RPL是不检查的。
转跳后程序的CPL(NewCS.RPL) = 转跳前程序的CPL( OldCS.RPL)
上面的安排就是概念1,2的意思,此时,CPL没有发生变化,纵使它执行了特权级(DPL)较高的代码。若访问时不满足要求,则发生异常。
目标是非一致代码段:
要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL≤CPL(CS.RPL)
转跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL
上面的安排就是概念3的意思和部分1的意思----主人(非一致代码段)只帮相同特权级的客人做事。因为前提是CPL=DPL,所以转跳后程序的 CPL(NewCS.RPL) = DestinationDescriptorCode.DPL不会改变CPL的值,特权级(CPL)也没有发生变化。如果访问时不满足前提 CPL=DPL,则引发异常。

通过调用门的跳转:当段间转移指令JMP和段间转移指令CALL后跟着的目标段选择子指向一个调用门描述符时,该跳转就是利用调用门的跳转。这时如果选择子后跟着32位的地址偏移,也不会被cpu使用,因为调用门描述符已经记录了目标代码的偏移。使用调门进行的跳转比普通跳转多一个步骤,即在访问调用门描述符时要将描述符当作一个数据段来检查访问权限,要求指示调用门的选择子的RPL≤门描述符DPL,同时当前代码段CPL≤门描述符DPL,就如同访问数据段一样,要求访问数据段的程序的CPL≤待访问的数据段的DPL,同时选择子的RPL≤待访问的数据段或堆栈段的DPL。只有满足了以上条件,CPU才会进一步从调用门描述符中读取目标代码段的选择子和地址偏移,进行下一步的操作。
从调用门中读取到目标代码的段选择子和地址偏移后,我们当前掌握的信息又回到了先前,和普通跳转站在了同一条起跑线上(普通跳转一开始就得到了目标代码的 段选择子和地址偏移),有所不同的是,此时,CPU会将读到的目标代码段选择子中的RPL清0,即忽略了调用门中代码段选择子的RPL的作用。完成这一步后,CPU开始对当前程序的CPL,目标代码段选择子的RPL(事实上它被清0后总能满足要求)以及由目标代码选择子指示的目标代码段描述符中的DPL进行特权级检查,并根据情况进行跳转,具体情况如下:

目标是一致代码段:
要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL ,RPL不检查,因为RPL被清0,所以事实上永远满足RPL≤DPL,这一点与普通跳转一致,适用于JMP和CALL。
转跳后程序的CPL(NewCS.RPL) = 转跳前程序的CPL( OldCS.RPL),因此特权级没有发生跃迁。

目标是非一致代码段:
当用JMP指令跳转时:
要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL<= CPL(CS.RPL)(事实上因为RPL被清0,所以RPL≤CPL总能满足,因此RPL与CPL的关系在此不检查)。若不满足要求则程序引起异常。
转跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL
因为前提是CPL=DPL,所以转跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL不会改变CPL的值,特权级也没有发生变化。如果访问时不满足前提CPL=DPL,则引发异常。
当用CALL指令跳转时:
要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL(RPL被清0,不检查),若不满足要求则程序引起异常。
转跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL
当条件CPL=DPL时,程序跳转后CPL=DPL,特权级不发生跃迁;当CPL>DPL时,程序跳转后 CPL=DPL,特权级发生跃迁,这是我们当目前位置唯一见到的使程序当前执行忧先级(CPL)发生变化的跳转方法,即用CALL指令+调用门方式跳转, 且目标代码段是非一致代码段。

总结:以上介绍了两种情况的跳转,分别是普通跳转和使用调用门的跳转,其中又可细分为JMP跳转和CALL跳转,跳转成功已否是由CPL,RPL和DPL 综合决定的。所有跳转都是从低特权级代码向同级或更高特权级(DPL)跳转,但保持当前执行特权级(CPL)不变,这里有点难于区别为什么说向高特权级跳转,又说特权级没变,这里“高特权级”是指目标代码段描述符的DPL,它规定了可以跳转到该段代码的最高特权级;而后面的CPL不变才真正说明了特权级未发生跃迁。我们可以看到,只有用CALL指令+调用门方式跳转,且目标代码段是非一致代码段时,才会引起CPL的变化,即引起代码执行特权级的跃迁,这是目前得知的改变执行特权级的唯一办法,如果各位读者还知道其他方法请留言告诉我。

---------------------------------------------------

一致代码段,非一致代码段

一致位:在描述符属性中TYPE(包含4个二进制位)字段的第2位。
当 S=1 时TYPE中的4个二进制位情况:
     3       2       1       0
   执行位 一致位 读写位 访问位
执行位:置1时表示可执行,置0时表示不可执行;
一致位:置1时表示一致码段,置0时表示非一致码段;
读写位:置1时表示可读可写,置0时表示只读;
访问位:置1时表示已访问,置0时表示未访问。

所以一致代码段和非一致代码段的意思就是指这个一致位是否置1,置1就是一致代码段,置0就为非一致代码段 。

保护模式特权级别DPL,RPL,CPL 之间的联系和区别的更多相关文章

  1. DPL,RPL,CPL 之间的联系和区别

    CPL是当前进程的权限级别(Current Privilege Level),是当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位. RPL说明的是进程对段访问的请求权限(Request P ...

  2. ASM:《X86汇编语言-从实模式到保护模式》第14章:保护模式下的特权保护和任务概述

    ★PART1:32位保护模式下任务的隔离和特权级保护  这一章是全书的重点之一,这一张必须要理解特权级(包括CPL,RPL和DPL的含义)是什么,调用门的使用,还有LDT和TSS的工作原理(15章着重 ...

  3. 详解 RPL、DPL、CPL 的关系

    保护模式中最重要的一个思想就是通过分级把代码隔离了起来,不同的代码在不同的级别,使大多数情况下都只和同级代码发生关系.Intel的80286以上的cpu可以识別4个特权级(或特权层) ,0级到3级.数 ...

  4. oslab oranges 一个操作系统的实现 实验二 认识保护模式

    https://github.com/yyu/osfs00 实验目的: 理解x86架构下的段式内存管理 掌握实模式和保护模式下段式寻址的组织方式. 关键数据结构.代码组织方式 掌握实模式与保护模式的切 ...

  5. x86保护模式 实模式与保护模式切换实例

    x86保护模式     实模式与保护模式切换实例 实例一 逻辑功能   以十六进制数的形式显示从内存地址110000h开始的256个字节的值    实现步骤: 1  切换保护方式的准备 2. 切换到保 ...

  6. 聊聊Dataguard的三种保护模式实验(上)

    Data Guard是Oracle高可用性HA的重要解决方案.针对不同的系统保护需求,DG提供了三种不同类型的保护模式(Protection Mode),分别为:最大保护(Maximum Protec ...

  7. CPU保护模式DPL、CPL简易理解

    现代INTEL CPU都有保护模式,实模式这两种CPU运行模式.当CPU加电,CPU初始化时就运行在是模式下,然后现代操作系统会从实模式跳转到保护模式! 为什么需要保护模式? 在最开始编程的汇编时代, ...

  8. ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务

    ★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...

  9. ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换

    15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...

随机推荐

  1. c# 委托详解

    1.委托声明 2.委托入门实例 namespace ConsoleApplication1 { public delegate void methodDelegate(string str); cla ...

  2. TCP/UDP差异

    首先,它 TCP是面向连接的.有序可靠的协议,然后UDP同TCP相对,那张脸无序连接不可靠的协议. 首先,为什么TCP它是面向连接的.由TCP如果传输是需要进行三次握手,这是client为了服务发送数 ...

  3. 【硬件】DELLserver硬件监控和DELL系统管理工具OMSA介绍

    1.1.1. DELLserver硬件监控和DELL系统管理工具OMSA介绍 本文介绍了利用使用Nagios和OMSA显示器DELLserver硬件健康状况,Nagios监控的方式是NRPE模式,须要 ...

  4. C#可扩展编程之MEF

    C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻 前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在 ...

  5. 真与假与c#,java中的不同之处

    /************真与假************/ /*C语言中:真(非0).假(0) * Java.C#中:真(true).假(false) * JavaScript中:真(非0.true. ...

  6. Jenkins中关于一些插件的使用方法

    最近在为公司搭建CI平台过程中,以及在具体项目实施过程中使用过的一些插件的具体用法: 1. ant插件 这个插件可能是我们最为经常使用的,若构建脚本是使用build.xml的,那构建引擎肯定会选择an ...

  7. Confluence, JIRA, Fisheye

    [tools]迁移Confluence, JIRA, Fisheye   [背景] 原先的Confluence, JIRA, Fisheye都部署在一台服务器(192.168.200.203)上,导致 ...

  8. [翻译]HBase 中的 ACID

    同前面翻译的一篇关联的,同作者的另一篇:ACID in HBase 这一篇不是单纯地描述一个问题,而是以 ACID 为主题,介绍了其在 HBase 中各个部分的体现及实现. ACID,即:原子性(At ...

  9. iOS基础 - UITableViewController

    1. 继承UITableViewController默认会设置数据源和代理,并且会自动遵守数据源和代理协议,并且self.tableView 相当于 self.view 2.更换控制器时,注意把sto ...

  10. Xcode开发和调试总结

    Xcode是iOS开发主要的工具.IDE.关于Xcode的细枝末节,可以参考苹果的官方文档或者众多的说明.此文档主要涉及常用开发和调试注意事项,参考版本为Xcode 5.1.1. 目标设置: 在此,我 ...