x86 的 TSS 任务切换机制

转自:http://blog.chinaunix.net/uid-587665-id-2732907.html



【0】写在前面

  • segment descriptors 构建保护模式下的最基本、最根本的执行环境。system descriptors 则构建保护模式下的核心组件:

  • 1、TSS descriptor 提供硬件级的进程切换机制

  • 2、LDT descriptor 供进程使用多个 descriptor
  • 3、Gate descriptor 提供 processor 权限级别的切换机制。

5.7.1、 TSS 提供的进程切换机制

  • TSS 是一段内存区域,存放进程相关的执行环境信息。初始化的 TSS 是由用户提供,进程切换时的保存信息由 processor 执行。

5.7.1.1、 三个元素构成 TSS 环境:

  • 1、 TSS descriptor:这个 descriptor 属于 system descriptor 类型,它的 S (system)位是 0。

    下面列出 TSS descriptors 的类型值:

    0001:  16-bit TSS
    0011: busy 16-bit TSS
    1001:  32-bit TSS
    1011: busy 32-bit TSS
    

      以上是 x86 下的 TSS descriptor 类型,分为 16 和 32 位 TSS,x64 的 long mode 下 32 位的 TSS descriptor 将变为 64 位 TSS descriptor。

  • 情景提示:

  • 关于 TSS 的 busy 与 available 状态:

    • 1、 TSS descriptor 的类型指明是 busy 与 available 状态。
    • 2、 TSS descriptor 的 busy 与 available 状态由 processor 去控制。即:由 processor 置为 busy 或 avaibable。 除了初始的 TSS descriptor 外。
    • TSS 的 busy 状态主要用来支持任务的嵌套。TSS descriptor 为 busy 状态时是不可进入执行的。同时防止 TSS 进程切换机制出现递归现象。
  • 2、 TSS selector 以及 TR(Task Register)寄存器

    • TR 寄存器的结构与 segment registers 是完全一致的,即:由软件可见的 selector 部分与 processor 可见的隐藏部分(信息部分)构成。

    • TR.selector 与 CS.selector 中的 selector 意义是完全一样的。其 descriptor 的加载也是一样的。

    • 即: TR.selector 在 GDT / LDT 中索引查找到 TSS descriptor 后,该 TSS descriptor 将被加载到 TR 寄存的隐藏部分。当然在加载到 TR 寄存器之前,要进行检查通过了才可加载到 TR 寄存器。若加载 non-TSS descriptor 进入 TR 则会产生 #GP 异常。

  • 3、 TSS 块(Task Status Segment)

    • 像 code segment 或 data segments 一样,最终的 TSS segment 由 TSS descriptor 来决定。 TSS descriptor 指出 TSS segment 的 base、limit 及 DPL 等信息。

    • TSS segment 存放 eflags 寄存器、GPRs 寄存器及相关的权限级别的 stack pointer (ss & sp)、CR3 等等信息。

5.7.1.2、 TSS 机制的建立

  • 对于多任务 OS 来说,TSS segment 是必不可少的,系统至少需要一个 TSS segment,但是现在的 OS 系统不使用 TSS 机制来进行任务的切换。

  • 情景提示:

    • TSS 存在的唯一理由是:需要提供 0 ~ 2 权限级别的 stack pointer,当发生 stack 切换时,必须使用 TSS 提供的相应的 stack pointer。
    • 但是:若提供空的 TSS segment,或者可以考虑以直接传递 stack pointer 的方式实现 stack 切换,即便是这样设计 processor 要读取 TSS segment 这一工作是必不可少的。
  • 下面的指令用来建立初始的 TSS segment:

    • LTR word ptr [TSS_Selector] /* 在 [TSS_selector] 提供 TSS selector */
      或:LTR ax /* 在 ax 寄存器里提供 TSS selector */

    • ltr 指令使用提供的 selector 在 GDT / LDT 里索引查找到 TSS descriptor 后,加载到 TR 寄存器里。初始的 TSS descriptor 必须设为 available 状态,否则不能加载到 TR。processor 加载 TSS descriptor 后,将 TSS descriptor 置为 busy 状态。

5.7.1.3、 TSS 进程切换的过程

  • 当前进程要切换另一个进程时,可以使用 2 种 selector 进行:使用 TSS selector 以及 Task gate selector(任务门符)。

    call 0x2b:0x00000000          /* 假设 0x2b 为 TSS selector */
    call 0x3b:0x00000000          /* 假设 0x3b 为 Task-gate  selector */
    
  • TSS 提供的硬件级进程切换机制较为复杂,大多数 OS 不使用 TSS 机制,是因为执行的效能太差了。上面的两条指令的 TSS 进程切换的过程如下:

  • 1、使用 TSS selector
      call 0x2b:0x00000000 /* 0x2b 为 TSS selector */
      这里使用 jmp 指令与 call 指令会有些差别,call 允许 TSS 进程切换的嵌套,jmp 不允许嵌套。

    • (1)processor 使用 TSS selector (0x2b) 在 GDT 索引查找第 5 个 descriptor

    • (2)processor 检查找到的 descriptor 类型是否是 TSS descriptor,不是的话将产生 #GP 异常。是否为 available TSS,若目标 TSS descriptor 是 busy 的话,同样将产生 #GP 异常。

    • (3)processor 进行另一项检查工作:权限的检查,CPL <= DPL 并且 selector.RPL <= DPL 即为通过,否则产生 #GP 异常。

    • (4)当前进程的执行环境被保存在当前进程的 TSS segment 中。

    • 情景提示:
        在这一步里,此时还没发生 TSS selector 切换,processor 把当前进程的环境信息保存在当前的 TSS segment 中。

    • (5)这里发生了 TSS selector 切换。新的 TSS selector 被加载到 TR.selector,而新的 TSS descriptor 也被加载到 TR 寄存的隐藏部分。

    • 情景提示:

      • (1)这里,processor 还要将旧的 TSS selector 保存在当前的 TSS segment(新加载的 TSS)中的 link 域。这个 TSS segment 中的 link 其实就是 old TSS selector 域,用来进程返回时获得原来的 TSS selector 。从而实现任务的嵌套机制。
      • (2)processor 将当前 eflags 寄存器的 NT(Nest Task)标志位置为 1,表明当前的进程是嵌套内层。
    • (6)processor 从当前的 TSS segment 取出新进程的执行环境,包括:各个 selector registers(segment registers)、GPRs、stack pointer (ss & sp)、CR3 寄存器以及 eflags 寄存器等。

    • 在这一步,在加载 selectors 进入 segment registers 之前,还必须经过相关的 selector & descriptor 的常规检查以及权限检查。通过之后才真正加载。否则同样产生 #GP 异常。

    • 情景提示:

      • processor 还要做另一项工作,就是:将新进程的 TSS descriptor 置为 busy 状态。使得新进程不能重入。
    • (7)processor 从当前的 CS:RIP 继续往下执行,完成这个 TSS 进程的切换。这个 CS: RIP 就是新加载的新进程的 cs : rip


  • 从上面的过程可以看出,使用 TSS 进程切换机制异常复杂,导致进程切换的效能太差了。比使用 call gate 以及 trap gate 慢上好多。若当中发生权限的改变,还要发生 stack 切换。
  • 进程的返回同样复杂。同样需要这么多步骤,总结来说,主要的时间消耗发生在新旧进程的信息保存方面。

  • 2、 使用 task gate selector

    • 另一种情况是使用 task gate selector 进行 TSS 进程切换,使用 task gate selector 除了可以 call/jmp 外,还可用在中断机制上,下面的两种情况:

        call 0x3b:0x00000000 /* 0x3b 为 task gate selector */
      或:int 0x3e /* 假设 0x3e 是 task gate 的向量 */

    • 这两种情形差不多,除了一些细微的差别外,不过是触发的机制不同而已。

    • processor 在 GDT 索引查找到的是一个 task gate descriptor,这个 task gate descriptor 中指出了目标的 TSS selector 。processor 从 task gate descriptor 里加载 TSS selector,剩下的工作和使用 TSS selector 进行切换进程是一致。

    • processor 访问 task gate descriptor 仅需对 task gate descriptor 作出权限检查:CPL <= DPL 并且 RPL <= DPL。在这里不需要作出对 TSS descriptor 的 DPL 权限进行检查。

    • gate descriptor 机制提供了一层间接的访问层,主要用来控制权限的切换。

  • 实际上:

    • 对于 call 0x2b:0x00000000 这条指令,processor 并不知道这个 selector 是 TSS selector 还是 task gate selector,在查找到 descriptor 后,processor 查看这个 descriptor 的 type 才能确定是 TSS selector 还是 task gate selector。
  • 最后需注意:

    • (1)使用 jmp 指令进行转移,processor 不会将 eflags 中 NT 标志位置 1
    • (2)使用中断机制下的 TSS 进程切换,processor 将不作任务的权限检查动作。

5.7.1.4、 TSS 进程的返回

  • 从 TSS 机制切换的进程在执行完后使用 iret 指令返回原进程进,同样会发生新旧 TSS segment 的更新动作。

  • 进程通过使用 ret 返回时,processor 将不会从嵌套内层返回到的嵌套外层进程,也就是不会返回原进程。processor 对 ret 指令的处理,只会从 stack pointer(ss : esp) 取返回地址。

  • 对于使用进程使用了 iret 中断返回指令时:
    • (1)processor 将会检查当前的 eflags.NT 标志位是否为 1,也就是检查当前进程是否处于嵌套的内层。
    • (2)eflags.NT = 1,processor 将从当前 TSS segment 中的 link(old TSS selector)域中取出原来进程的 TSS selector。
    • (3)processor 将不作任何的权限检查,TSS selector 被加载到 TR.selector,TSS descriptor 同时被加载到 TR 的隐藏部分。
    • (4)processor 将清除当前的 eflags.NT 为 0。若是使用 ret 指令返回的,processor 是不会清 eflags.NT 为 0
    • (5)从 TSS segment 中加载新的进程执行环境,从新的 CS:EIP 处继续执行。 将原来的 TSS descriptor 重新置为 available 状态,使得可以再次进入。

    • 由上可得,processor 遇到 ret 指令时,是不会对 eflags.NT 进行检查的。而使用 iret 指令,processor 将对 eflags.NT 进行检查。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring安全性_具有PreAuthorize的Spring方法安全性

spring安全性朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 本教程将探讨使用Spring Security在Spring Boot中配置身份验证和授权的两种方法。…

animiz动画制作软件_AN动画制作软件

AN基础介绍我们先了解一些基本概念&#xff0c;才能帮助我们更好的进行下面一系列的操作。1.图层。图层就像是含有文字或图形等元素的胶片&#xff0c;一张张按顺序叠放在一起&#xff0c;组合起来形成页面的最终效果。图层可以将页面上的元素精确定位。图层中可以加入文本、图…

关于一致/非一致代码段与TSS 关系的个人看法

【0】概念定义 0.1&#xff09;一致代码段: 简单理解&#xff0c;就是操作系统拿出来被共享的代码段,可以被低特权级的用户直接调用访问的代码&#xff0c; 但是特权级高的程序不允许访问特权级低的数据. 通常这些共享代码&#xff0c;是”不访问”受保护的资源和某些类型异…

python预处理标准化_tensorflow预处理:数据标准化的几种方法

tensorflow预处理&#xff1a;数据标准化的几种方法发布时间&#xff1a;2018-08-09 19:39,浏览次数&#xff1a;1774, 标签&#xff1a;tensorflow数据归一化问题是数据挖掘中特征向量表达时的重要问题&#xff0c;当不同的特征成列在一起的时候&#xff0c;由于特征本身表达方…

三思笔记_使用反射前先三思

三思笔记介绍 有时&#xff0c;作为开发人员&#xff0c;您可能会遇到无法使用new运算符实例化对象的情况&#xff0c;因为其类名称存储在配置XML中的某个位置&#xff0c;或者您需要调用一个名称指定为注释属性的方法。 在这种情况下&#xff0c;您总会有一个答案&#xff1a;…

分页机制总结

【0】写在前面&#xff08;分页机制&#xff09; 0.0&#xff09; source code from orange’s implemention of a os and text description from Zhaojiong’s perfect analysis of Linux kernel and for complete code ,please visit https://github.com/pacosonTang/Orange…

python程序填空题参照代码模板、完善代码_python二级考试操作题11.pdf

综合应用题参照代码模板完善代码&#xff0c;实现下述功能。文件ngchina.html 保持了网页源代码&#xff0c;请将该页面中图片的URL 提取出来,并输出所有图像的URL。习题讲解#P301#读取HTML 文件内容def getHTMLlines(htmlpath):f open(htmlpath,"r",encoding utf-…

Struts2学习笔记

文章目录Struts2 的核心开发包Struts2 配置文件Struts2 域对象Struts2 编程流程Action 组件使用通配符配置 ActionAction 中如何访问 Session通过 ActionContext 对象访问 Session 对象&#xff08;不推荐&#xff09;通过实现 SessionAware 接口访问 sessionAction 如何访问 r…

如何从文件系统中读取文件内容

【0】写在前面 0.0&#xff09; text description from orange’s implemention of a os &#xff0c;文末总结系个人臆测出的干货 【1】intro to FAT12&#xff08;file allocation table 12&#xff09;文件系统格式&#xff08;from Baidu Baike&#xff09; &#xff08;…

java微服务,微在哪_Java:ChronicleMap第3部分,快速微服务

java微服务,微在哪标准Java Maps需要在启动时进行初始化。 了解如何利用可从文件初始化的ChronicleMaps并显着减少微服务启动时间&#xff0c;以及如何在JVM之间共享Maps。 内置的Map实现&#xff08;例如HashMap和ConcurrentHashMap速度很快&#xff0c;但是必须先使用映射进…

excel离散度图表怎么算_Excel数据分析——离散值排除-excel直方图

今天举例的数据继续沿用昨天做出来的结果&#xff0c;至于这组数据还要接着用多久~~可能要混到我讲不下去为止吧~~~我们通过两个不同的拟合公式得到了两组不同的残差值&#xff0c;数据情况如下&#xff1a;有没有觉得看上面那张散点图有点糊啊&#xff1f;没错&#xff0c;问题…

drools dmn_Drools DMN最新开源引擎性能改进

drools dmn我们一直在寻求改善Drools DMN开源引擎的性能。 我们最近审查了DMN用例&#xff0c;其中输入数据节点的实际输入总体有所不同。 这突出显示了引擎的次佳性能&#xff0c;我们在最新版本中对此进行了改进。 我想分享我们的发现&#xff01; 基准制定 当我们开始为此用…

制作FAT12软盘以查看软盘的根目录条目+文件属性+文件内容

【-1】Before for specific info , please visit http://wiki.osdev.org/Loopback_Device 【0】我们先上干货&#xff0c;看到效果后&#xff0c;我们再说明每个步骤的缘由&#xff1b; 【1】进入挂载目录&#xff0c;添加相关文件&#xff08;依个人意愿&#xff09; Attenti…

如何取消高亮显示重复项_如何将重复数据突出显示?

将表格中一列数据中重复的&#xff0c;使用特殊颜色突出显示或者使用一些符号标记出来。例如&#xff1a;一个供应商&#xff0c;可以邀请别的供应商加入成为联合体&#xff0c;报表要显示所有供应商&#xff0c;然后供应商最后一列显示所有联合体&#xff0c;当联合体供应商跟…

Maven的maven-source-plugin插件详解

maven-source-plugin 这个插件专门负责将项目源文件打成包的&#xff0c;该插件在 pom.xml 中的配置如下&#xff1a; <build><plugins><plugin><artifactId>maven-source-plugin</artifactId><version>3.0.1</version><configu…

Maven Java Web Project打包详解/如何打包

文章目录打包部署构件&#xff08;Artifacts&#xff09;打源码包方式一&#xff1a; 命令行方式方式二&#xff1a;使用 IDE将源码包发布到本地 Maven 仓库中涉及到案例项目的结构&#xff1a; 打包部署构件&#xff08;Artifacts&#xff09; war 格式的部署构件可以直接放…

四位共阳极数码管显示函数_数码管模块.doc

数码管模块数码管1、概 述数码管模块采用四位共阳极数码管&#xff0c;用于显示数字和少数特殊字符。可以在机器人项目中使用该模块&#xff0c;用于显示速度、时间、分数、温度、距离等传感器的值。同时&#xff0c;Makeblock提供易于编程的Arduino库&#xff0c;使用户能够方…

java中的可检查和不检查_检查Java测试中发生了什么

java中的可检查和不检查有人想到了在Java单元测试中使用try和catch块的想法&#xff1a; Test public void test() { try { callSomeCode(); } catch (Exception e) { assertEquals( "foo" , e.getMessage()); } } 上面的内容很诱人&#xff0c;但不起作用 。 如果…

FAT12中,如何定位大于一个扇区(512B)的文件内容

【0】README 0.1&#xff09;本文旨在于 演示在FAT12中&#xff0c; 如何取定位大于 512B 的文件内容&#xff0c;和查看它&#xff1b;0.2&#xff09;如何制作FAT12文件系统&#xff0c;以及如何向文件中添加temp.txt文件&#xff0c;参见&#xff1a; { http://blog.csdn.n…

通过Struts2的拦截器实现文件上传/上传文件功能

struts.xml配置内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN""http://struts.apache.org/dtds/struts-2.3.dtd&qu…