在简单的内核与程序加载部分,不管是内核还是用户程序,是把所有的的段描述符都放在GDT中,为了有效地在任务之间进行隔离,处理器建议每个任务都有自己的描述符表,称为局部描述符表(LDT),并把那些专属自己的段放在LDT中。为了访问这些LDT,处理器使用了局部描述符表寄存器(LDTR)。
在一个多任务系统中,LDTR只指向当前任务的LDT,LDTR也包含了32位线性基地址和16位界限。在任务切换过程中,为了保存任务的状态,并在下次重新执行时恢复他们,每个任务都应当用一个额外的内存区域保存相关信息,叫做任务状态段(TSS),任务状态段有固定的的格式,最小尺寸是104字节。处理器固件能够能够识别TSS中的每个元素,并在任务切换的时候读取其中的信息,TSS部分由TR寄存器指向。当任务切换发生的时候,TR寄存器的内容也会跟着指向新任务的TSS。具体过程如下:

首先,处理器将当前任务的现场信息保存到由TR指向的TSS;然后,再使TR寄存器指向新的任务的TSS,并从新任务的TSS中恢复现场。
注意:TSS中的SS0、ESP0、SS1、ESP1、SS2、ESP2域是静态的,返回时处理器不会更改它们,除非软件进行修改。

全局空间和局部空间

多任务的管理是交给操作系统进行,涉及到和所有任务都有关系的全局性管理工作,如空闲内存的查找和分配,回收已终止任务的内存空间、设备访问的排队和调度等。
对于每个任务来说包括两个部分,全局部分和私有部分。全局部分(GDT)是所有任务共有的,含操作系统的软件和库程序以及可调用的系统服务和数据,私有部分(LDT)是每个任务各自的数据和代码。

特权级保护

当处理器正在一个代码段中取指令和执行指令时,那个代码段的特权级叫做当前特权级,正在执行的代码段其选择子位于段寄存器CS中,其最低两位就是当前特权级的数值。
应用程序在加载时,操作系统负责创建GDT、LDT、分段和描述符(给出用户程序特权级),用户程序只提供各段在用程序的偏移地址,由此便可建立描述符的内容。
代码段的特权级检查很严格,一般控制转移只允许发生在两个特权级相同的代码段之间。为了让低特权级的应用程序能够调用高特权级的操作系统例程,处理器也提供的解决办法:

  • 将高特权级的代码段定义为依从的,将控制转移到依从的代码段的前提是当前特权级CPL必须低于或等于目标代码段的DPL。
    依从的代码段不是在它的DPL特权级上运行,而是在调用程序的特权级上运行。当控制转移到依从的代码段执行时,不改变当前特权级CPL,段寄存器CS的CPL字段不发生改变,被调用过程的特权级依从调用者的特权级。
  • 另一种在特权级之间转移控制的方法是使用门。
    门是另一种形式的描述符,称门描述符,和段描述符不同,段描述符用于描述内存段,门描述符用于描述可执行的代码(门描述符提供的是段选择子)。门有中断门/陷阱门,任务门以及调用门。

门描述符也是64位,在调用门描述符中定义了例程所在代码段的选择子,以及段内偏移,想要通过门转移控制,可以使用ljmp指令,但不会改变当前特权级别;使用lcall指令则当前特权级会提升为目标代码的特权级,但是除了从高特权级别的代码返回外,不允许再将控制转移到特权级低的代码段。

调用门

当用户程序被加载的时候,它的特权级是由操作系统赋予的,毕竟局部描述符表是由操作系统建立的,并且用户程序的特权级为3,为了访问操作系统提供的例程(例程的特权级为0),因此需要调用门用于不同级别特权级用户程序的控制转移,其本质上是一个描述符,可以安装在GDT或LDT中(GDT和LDT的修改与建立是操作系统干的,所以很合理)。调用门描述符给出了例程所在代码段的选择子,有了段选择子,就能访问描述符表得到代码段的基地址,例程在代码段的偏移量也是在描述符中指定的,很显然,在通过门调用例程的时候不能使用指令给出偏移量,这也就起到了保护作用。门有几种类型,TYPE字段1100表示为调用门。
注意栈段的特权级(CPL)必须与当前特权级保持一致,比如一个特权级为3的程序必须使用自己的特权级为3的栈工作。当通过调用门进入0特权级栈的代码段执行时,栈要进行切换,原先3特权级的栈切换到0特权级的栈。这主要防止因栈空间不足而产生不可预料的问题,同时也防止栈数据的交叉引用。3特权级的任务最多额外定义三个栈,描述符特权级别分别是0,1和2,在控制转移到0,1和2的特权级时使用,创建过程由操作系统来完成。这些额外的栈,其描述符位于任务自己的LDT中,同时还要在TSS中登记,因为任务切换是由处理器固件自动完成的,处理器需要根据TSS中的信息完成这一过程。在通过调用门访问例程时,因为涉及到特权级的改变,栈要更换,为了使例程能获得参数,必须将参数从旧栈复制到新栈,参数的复制是处理器自动完成的,但它必须知道参数的个数,调用门描述符中还有一个5位的参数个数字段,就是说至多允许传入31个参数。调用门描述符中的DPL和目标代码段描述符DPL用于决定哪些特权级的程序可以访问此门(门描述符DPL一般为3)。一般同时要求:

  • 当前特权级的CPL和请求特权级的RPL大于等于调用门描述符的DPL;
  • 当前特权级的CPL小于等于目标代码段描述符DPL。

借用调用门,当前程序的执行流从低特权级的代码段转入高特权级的代码段时,如果那是个非依从的代码段,当前特权级也随之变为目标代码段的特权级。当调用者和被调用者特权级相同时,特权级没有变化,在控制转移过程中不会发生栈切换。用户程序只可以通过lcall进入门提高自身的特权级,这时用户程序的代码段选择子也会作为返回地址压入栈中。

为了让用户程序提供的RPL与自身的特权级一致,通过arpl指令传递给操作系统的段选择子作为目的操作数,用户程序的段选择子作为源操作数(可以从栈中取得)实现。

加载用户程序并创建任务

加载前的准备

加载程序并创建一个任务,需要很多数据,比如程序的大小、加载位置等。当任务执行结束,还要依据这些信息来回收它所占的内存空间,在多任务系统中,为了在任务之间切换和轮转,必须能够追踪到所有正在运行的任务,记录它们的状态,或者根据它们的状态进行操作。

为了满足以上要求,内核应当为每一个任务创建一个内存区域,来记录任务的信息和状态,称为任务控制块(TCB)。在用户程序正式加载之前,操作系统已经为其创建了任务控制块,并要通过栈传入两个参数,分别是用户程序起始逻辑扇区号,以及它的任务控制块TCB的线性地址。并且还要做三件事:

  • 分配一块内存,作为LDT;
  • 将LDT的大小和起始线性地址登记在任务控制块TCB中;
  • 分配内存并加载用户程序,并将其大小和线性地址登记在TCB中。

这样看来TCB的内容至少包括LDT起始线性地址及其大小;用户程序线性地址及其大小。后面还会了解到其中包括:用户程序段的选择子;不同特权级栈的信息(后面更新到TSS中);LDT选择子(后面更新到TSS中);TSS的基地址及其大小;TSS描述符选择子。一般提到选择子都是用于选择特定的描述符。

加载用户程序

(1)创建局部描述符表
当应用程序被加载进内存后,需要在LDT中创建段描述符,描述符的特权级也会被设置成3。通过相应的算法计算出描述符在LDT中的索引号,再计算出选择子,选择子的特权级也设置成3,登记到TCB中,并回填到用户程序的头部。
(2)重定位
之后要重定位用户程序的符号地址表,替换符号为调用门选择子和32位段内偏移(偏移也用不到,由门确定),内核符号地址表中包含符号(即例程)的偏移地址和段选择子,因为在创建这些调用门时,选择子的RPL字段是0(调用门安装在全局符号表中),但复制到用户程序的符号地址表中,应当更改为特权级应改为3,下次再访问全局描述表中的门时,请求特权级为3,虽然是内存的同一位置,但因为访问的是门(TYPE:1100标识),所以可以访问这块内存。
(3)创建0、1和2的特权级的栈
任务在运行时,需要调用内核或者操作系统的例程。可以认为是从同一个任务的局部地址空间转移到全局地址空间工作,并且这个过程涉及到特权级的变化,需要通过门,但这也会改变当前特权级的CPL,同时还要切换到与目标代码段特权级相同的栈。为此要为每个任务定义额外的栈,因为还没有创建TSS,有必要先将这些栈信息登记在TCB中保存。
(4)安装LDT描述符到GDT中
因为GDT只有一个,所以其基地址用一个寄存器就可以完成,而LDT有多个,其基地址以描述符的形式安装在全局描述符表中。当要使用LDT时,可以用它们的选择子来访问GDT,将LDT描述符加载到LDTR中。关于LDT描述符的创建主要通过TCB中的LDT基地址及其长度,TYPE固定为0010表明LDT描述符。LDT描述符最后要加到全局描述符表GDT中,并将其选择子写入TCB中。
(5)创建任务状态段TSS
创建TSS后,要把TSS的基地址和界限登记到TCB中,将来创建TSS的描述符时用得着(先有TSS再有其描述符以便于找到)。在TSS中登记0,1和2特权级栈的段选择子,以及它们的初始栈指针,所有的栈信息都在TCB中,从TCB中取出,然后填写到TSS中的相应位置。在TSS中登记当前任务的LDT描述符选择子,在任务切换时,处理器需要用这里的信息找到当前任务的LDT。
(6)安装TSS描述符到GDT中
和LDT一样,也必须在GDT中安装TSS的描述符,一方面为了对TSS进行段和特权级的检查,另一方面也是执行任务切换的需要。当使用长跳转指令的操作数是TSS描述符选择子时,处理器执行任务切换操作。在GDT中安装好TSS描述符,并返回描述符的选择子登记在TCB中。

任务切换前的设置

当一个任务正在执行时,处理器的各个部分都和这个任务息息相关,段寄存器指向该任务所使用的内存段;通用寄存器保存着该任务的中间结果。离开当前任务转到另一个任务开始执行时,要保存旧任务的各种状态,并恢复新任务的运行环境。
TSS用来保存任务切换过程中的旧任务的各种状态数据,其描述符在GDT中创建,其选择子要传送到任务寄存器TR中。

任务切换的方法

(1)借助中断
这是现代操作系统抢占式任务切换的基础。在保护模式下,中断向量表不再使用,取而代之的是中断描述符表,它与GDT、LDT是一样的,用于保存描述符。但它保存的是门描述符,包括中断门、陷阱门和任务门。当中断发生时,处理器就用中断号乘以8(因为每个描述符占8个字节),作为索引访问中断描述符表取出门描述符。门描述符中有中断处理过程的代码段选择子和段内偏移,接着转移到相应的位置去执行。

一般的中断处理可以使用中断门和陷阱门,类似于调用门只是从任务的局部空间转移到更高特权级别的全局空间去执行,本质上是一种任务内的控制转移行为。中断门和陷阱门允许在任务内实施中断处理,转到全局空间去执行一些系统级的管理工作,本质上也是任务内的控制转移行为。

但在中断发生时,如果该中断号对应的门是任务门,那么性质就完全不同,必须进入任务切换:中断当前任务的执行;保护当前任务的现场,并转换到另一个任务去执行。任务门描述符的格式主要包括:TSS选择子,DPL(但对因中断发生的任务切换不起作用),TYPE(00101)等。任务门用于中断发生时任务的切换,任务的切换时,必须找到新任务的TSS。在转移到新任务处理之前还应当根据TR的指向保存当前任务的状态,当任务切换后,TR指向新任务的TSS。无论是普通的中断处理过程还是任务切换,都是要返回的。任务切换的返回是根据EFLAGS中NT位为1(说明当前正在执行的任务嵌套与其他任务内),和TSS任务链域中前一个任务的TSS描述符选择子返回到前一个任务。
对新任务的处理包括:把老任务的的TSS选择子填写到新任务TSS中的任务链域,同时将新任务EFLAGS寄存器NT位置1,以允许返回到老任务继续执行,同时把TSS描述符的B位置1。
任务的返回通过iret指令,此时要检查NT位,并且任务返回处理器固件把当前任务的EFLAGS寄存器的NT位改为0,并把TSS描述符的B位改为0。保存当前任务的状态后,接着用被中断任务的TSS恢复现场。
(2)远转移指令
call指令发起的任务切换与中断引起的任务切换相似,和call指令不同,使用jmp指令发起的任务切换不会形成任务之间的嵌套关系。执行任务切换时,旧任务的TSS描述符B位清零,变为非忙状态,EFLAGS寄存器的NT位不变,新任务TSS描述符B位置1,进入忙状态,EFLAGS的NT位保持从TSS中加载时不变。

特权级保护和任务切换相关推荐

  1. 任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34

    任务和特权级保护(三)--<x86汇编语言:从实模式到保护模式>读书笔记34 5.2.7 在GDT中创建LDT描述符 处理器要求在GDT中安装每个LDT的描述符.当要使用这些LDT时,可以 ...

  2. 任务和特权级保护(一)——《x86汇编语言:从实模式到保护模式》读书笔记27

    本文及后面的几篇文章是原书第14章的读书笔记. 1.LDT(局部描述符表) 在之前的学习中,不管是内核程序还是用户程序,我们都是把段描述符放在GDT中.但是,为了有效实施任务间的隔离,处理器建议每个任 ...

  3. 【OS学习笔记】二十四 保护模式七:调用门与依从的代码段----特权级保护

    学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 上一篇文章学习了保护模式下的任务与任务隔离,以及简单介绍了保护模式下 ...

  4. X86汇编语言从实模式到保护模式16:特权级和特权级保护

    目录 1. 特权级保护机制 1.1 基础段保护机制的不足 1.2 特权级划分 1.3 特权级的表示 1.3.1 当前特权级CPL 1.3.2 描述符特权级DPL 1.3.3 请求特权级RPL 1.4 ...

  5. 【OS学习笔记】二十五 保护模式七:任务和特权级保护对应的汇编源代码

    本汇编代码是以下两篇文章讲解的内容的内核代码; [OS学习笔记]二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念 [OS学习笔记]二十四 保护模式七:调用门与依从的代码段----特权级保护 ...

  6. 四,中断:中断程序(汇编和C语言)、idt、IDTR、8259A、8253以及发生中断时候的压栈细节和特权级保护

    中断: 由于CPU获知了计算机中发生的某些事,CPU暂停正在执行的程序,转而去执行处理该事件的程序,当这段程序执行完毕后,CPU继续执行刚才的程序,整个过程称为中断处理,也称为中断.没有中断,操作系统 ...

  7. x86 --- 任务隔离特权级保护

    程序是记录在载体上的数据和指令. 程序正在执行时的一个副本叫做任务 所有段描述符都放在GDT --> 不做区分. 内核程序(任务)所占段在GDT中,用户程序(任务)所占段在LDT中 --> ...

  8. 任务和特权级保护(五)——《x86汇编语言:从实模式到保护模式》读书笔记36

    任务和特权级保护(五)--<x86汇编语言:从实模式到保护模式>读书笔记36 修改后的代码,有需要的朋友可以去下载(c14_new文件夹).下载地址是: GitHub: https://g ...

  9. 任务和特权级保护(四)——《x86汇编语言:从实模式到保护模式》读书笔记35

    任务和特权级保护(四)--<x86汇编语言:从实模式到保护模式>读书笔记35 7. 正式进入用户程序的局部空间 67 mov ebx,message_1 68 call far [fs:P ...

最新文章

  1. Java8-Lambda表达式
  2. Eclipse快捷键 10个最有用的快捷键 提高开发效率
  3. 深度学习100例-卷积神经网络(CNN)彩色图片分类 | 第2天
  4. 学习笔记(十四)——MySQL(CRUD)
  5. 云服务器镜像麻烦吗_简单说说云服务器的镜像功能作用
  6. 如何实现同一个页面里面两个页面的相互切换(window.onscroll)
  7. c# Message const
  8. restful服务端客户端_测试RESTful服务的客户端
  9. Java Mybatis
  10. 微软宣布已获批:重新向华为出口软件!
  11. linux alias使用
  12. 电气绘图软件-AutoCAD Electrical:介绍
  13. 竞品分析 | 荔枝VS喜马拉雅FM:有声音频APP的发展与社交
  14. 幼儿园观察记录的目的和目标_幼儿园游戏观察记录
  15. 用微信网页版阅读文章
  16. scheme 语言概述
  17. 交管123缴费显示代理服务器异常,交管12123服务异常怎么回事?交管12123网络请求失败怎么办...
  18. 模拟QQ心情图片上传预览
  19. Python 重载向量加法运算符 +
  20. 中国机器视觉市场研究报告

热门文章

  1. 数据结构判断链表是否为空:
  2. 《乐高EV3机器人搭建与编程》一1.1 打开MINDSTORMS EV3包装盒
  3. MarginNote3占用空间很大的解决方案
  4. 网约车调用高德地图计算距离和时间
  5. xmapp启动MySQL出错
  6. 国网项目入场安规考试题库
  7. 赵永泽计算机竞赛,工学院举办2021年机械制图竞赛
  8. Ubuntu开机遇到 clean files blocks问题
  9. 年薪30万,达到人生巅峰,入职字节一个月,我却被无情碾压
  10. JDK API官方文档