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 进行检查。
x86 的 TSS 任务切换机制相关推荐
- Spark之Master主备切换机制原理
Spark之Master主备切换机制原理
- 达梦数据库实时主备集群的同步机制和切换机制
DM数据守护介绍 1. DM 数据守护(Data Watch) 是一种集成化的高可用.高性能数据库解决方案,是数据库异地容灾的首选方案.通过部署 DM 数据守护,可以在硬件故障(如磁盘损坏).自然灾害 ...
- Qt编写输入法源码V2019,未采用Qt系统层输入法框架,独创输入切换机制
Qt编写输入法源码V2019 未采用Qt系统层输入法框架,独创输入切换机制. 纯QWidget编写,支持任何目标平台(亲测windows.linux.嵌入式linux等),支持任意Qt版本(亲测Qt4 ...
- NR BWP切换机制,切换时延
目录 1. BWP概述 2. BWP切换机制 RRC based BWP切换 Timer based BWP切换 DCI based BWP切换 3. BWP切换时延 1. BWP概述 在之前的博客h ...
- 【中继协助频谱切换】基于中继协助的频谱切换机制的MATLAB仿真
1.软件版本 MATLAB2013b 2.本算法理论知识 在认知无线电网络(Cognitive Radio Network,简称CRN)中引入协作通信可以提高系统的分集增益.CRN中,协作通信的模式主 ...
- f5双机配置_F5负载均衡器双机切换机制及配置
文档来源为 : 从网络收集整理 .word 版本可编辑 . 欢迎下载支持 . 1 F5 负载均衡器双机切换触发机制及配置 1 F5 双机的切换触发机制 1.1 F5 双机的通信机制 F5 负载均衡器的 ...
- 【连载】从单片机到操作系统⑥——FreeRTOS任务切换机制详解
大家晚上好,我是杰杰,最近挺忙的,好久没有更新了,今天周末就吐血更新一下吧! 前言 FreeRTOS是一个是实时内核,任务是程序执行的最小单位,也是调度器处理的基本单位,移植了FreeRTOS,则避免 ...
- m基于中继协助的认知无线电频谱切换机制的matlab仿真分析
目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 认知无线电网络在进行频谱切换的时候,最为重要的问题是如何以最少的频谱切换次数实现频谱切换,同 ...
- f5双机配置_[整理]F5负载均衡器双机切换机制及配置.
------------- ------------- F5 负载均衡器双机切换触发机制及配置 1 F5 双机的切换触发机制 1.1 F5 双机的通信机制 F5 负载均衡器的主备机之间的心跳信息可以通 ...
最新文章
- 硬核!我的导师手写129页毕业论文,堪比打印!
- 今天做了一个复杂的table
- python字典赋值方法_python如何给字典的键对应的值为字典项的字典赋值
- .NET如何写正确的“抽奖”——数组乱序算法
- C#.Net工作笔记014---C#中internal的意思
- 【U-net】【粗读】Retinal blood vessel segmentation using fully convolutional network with transfer...
- 实现横向排列的几种方案
- MAC 上的 Live Writer : ecto
- Vivado2018.3手把手详细下载
- 怎么查期刊是核心、是EI,还是SCI,或者说有哪些不是吧?
- 微型计算机8086工作原理,8086到80486微型计算机系统原理与接口
- dell 服务器启用虚拟化,打开DELL R410服务器BIOS虚拟化步骤(图文教程)
- 利用 JavaScript 快速切换正体中文和简体中文
- Windows系统封装步骤
- php7米酷cms,米酷CMS6.2修改版 支持PHP7 独家首发 - 百码云
- L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误
- OpenCV开发笔记(四十九):红胖子8分钟带你深入了解轮廓识别(图文并茂+浅显易懂+程序源码)
- 服务器热备份、虚拟,VMware虚拟机热备份的几种方法
- 电口以太网物理层一致性测试原理与过程
- 基于OFBiz的E-TICKET(在线咨询管理)模块
热门文章
- Frogs HDU - 5514
- 牛客网【每日一题】7月30日题目精讲—Xor Path
- P4022-[CTSC2012]熟悉的文章【广义SAM,dp,单调队列】
- P3703-[SDOI2017]树点涂色【LCT,线段树】
- P1337-[JSOI2004]平衡点/吊打XXX【模拟退火】
- nssl1477-赛【对顶堆,贪心】
- jzoj4051-序列统计【NTT】
- 【线段树】扇形面积并(P3997)
- 【矩阵乘法】生成树计数(luogu 2109/NOI 2007)
- YL杯超级篮球赛(jzoj 1325)