一个任务由两部分组成

  • 任务执行空间,由代码段,栈段,和一个或多个数据段组成
  • 任务状态段(TSS)

如果操作系统使用处理器特权级机制,那么任务执行空间会对每个特权级提供不同的栈(实际上是对0, 1, 2三个特权级分别提供不同的栈)

注,用户程序的特权级是3,不是上述三个栈中的任何一个,而是SS : ESP表示的栈

一个正在被执行的任务状态包括

  • 任务当前执行的空间,由各种段选择子决定(CS, DS, SS, ES, FS和GS)。在线性地址空间中,是一个段空间
  • 通用寄存器状态,包括EAX, ECX, EDX, EBX, ESP, ESI和EDI的值
  • EIP寄存器的状态,即EIP的值
  • CR3控制寄存器的值
  • 任务寄存器(TR)的状态
  • LDTR寄存器的状态
  • I/O内存映射的基地址(包含在TSS中),(共享内存?)
  • 三个栈指针,分别指向特权级0, 1, 2的栈地址
  • 上一个被执行的任务的link(地址)

任务状态中”上一个被执行的任务的link”指的是

当任务A使用CALL指令调用任务B时,在任务B的任务状态中会包含任务A的地址,以便于当B执行完成后可以返回到任务A接着执行。很像汇编中CALL指令调用函数时将下一条语句的地址入栈。

软件或者处理器可以使用以下几种方法调度一个任务

  • 显式使用CALL指令调用某个任务
  • 显式使用JUMP指令跳转到某个任务
  • 由处理器隐式调用中断处理任务
  • 隐式调用异常处理任务(也是由处理器?)
  • 如果EFLAGS寄存器的NT标志被设置,那么可以使用IRET指令在返回时隐式调转到某个任务

上述的所有方法都是通过一个指向任务段描述符的选择子或者指向任务门描述符的选择子实现的。

在任务切换过程中,假设由于某种原因(通常是属于某个任务的时间片用光),处理器将从当前正在执行的任务A切换到另一个任务B。此时,处理器需要记录任务A的所有状态以便当切换回任务A时就好像没离开过一样,所以,处理器会先将任务A的状态(上面列出的任务状态)存储在任务A的TSS中(任务状态段)。然后将任务A挂起,并将任务B的状态加载到处理器上(从B的TSS中),以此完成任务切换。

虽然听起来任务切换比较简单,就是保存A,执行B。但是在这个看似简单的过程中,处理器做了非常多的事情,不过再次之前,先看一下都在什么时候处理器会执行任务切换
- 当前任务A执行了JMP或CALL指令显示调用任务B。JMP和CALL的操作数为段选择子,指向GDT中任务B的TSS段描述符
- 当前任务A执行了JMP或CALL指令显示调用任务B。JMP和CALL的操作数为段选择子,指向GDT或任务B的LDT中的任务门描述符
- 当前任务A出现一个指向IDT中任务门描述符的中断/异常向量
- 当前任务A执行了IRET指令且EFLAGS寄存器中的NT标志位被设置

当发生任务切换时,处理器依次执行如下操作

  1. 从任务门或上一个任务的link中获取任务B的TSS段选择子作为JMP或CALL的操作数
  2. 核查任务A是否可以切换到任务B。这里需要应用特权级规则,即任务A的CPL和任务B的TSS段选择子的RPL必须小于任务B的TSS段描述符或任务门的DPL。另外对于中断/异常(不包括INT n中断)以及IRET指令则不需要进行核查
  3. 核查TSS段描述符是否有一个有效的段界限
  4. 核查任务B是处于空闲状态(available)还是忙碌状态(busy),检查段描述符中B标志位,这步骤用于防止递归调用任务
  5. 核查任务A的TSS,任务B的TSS和切换过程中被使用的所有段描述符是否都已经被映射到物理内存中(分页机制可能会导致某些数据被存放到外存中)
  6. 对于JMP和IRET指令,因为不需要返回当前任务A,所以将任务A的段描述符的B标签置0,表示任务A处于空闲状态;对于CALL指令,因为需要返回当前任务A,所以将B标签置1,表示任务A处于忙碌状态,防止递归调用任务A
  7. 如果任务切换由IRET指令引发(此时NT标志位是1),那么在转移过程中会将NT标志置0。如果由其他因素引发(CALL, JMP,中断,异常),则保持NT标志位不变
  8. 保存当前任务A的任务状态,这个过程中会通过TR获取任务A的TSS地址,然后将任务A的所有运行状态(主要是各个寄存器的值)保存在任务A的TSS中
  9. 如果任务切换由CALL,中断或异常引发,那么处理器将会将任务B的NT标志位置1。如果由IRET或JMP指令引发,那么处理器会从任务B的TSS中读取NT的值
  10. 如果任务切换由CALL,JMP,中断或异常引发,那么处理器会设置任务B的段描述符的B标签。如果由IRET引发,则保持不变
  11. 将任务B的段选择子和段描述符加载到TR寄存器中
  12. 将任务B的TSS加载到处理器中,本质是设置各种寄存器的值
  13. 加载有关的段描述符
  14. 开始执行任务B

任务门描述符提供对TSS的间接引用,可以位于GDT,LDT以及IDT中,描述符中保存着段选择子,通过段选择子,可以在GDT中找到TSS段描述符以获取TSS的基地址

当程序使用CALL或JMP指令尝试条用任务门时,CALL和JMP的操作数实际上是任务门的选择子,通过选择子可以找到在GDT,LDT或IDT中的任务门描述符。不过,任务门选择子的CPL和RPL必须小于等于门描述符的DPL

任务门描述符的结果如下


TSS(任务状态段)的结果如下


可以看出TSS中主要就是各种寄存器的值,这主要是为了当任务切换时,把当前正在执行的任务的各种状态保存下来,这样,当又执行这个任务时,就可以从TSS中获取刚离开时这个任务的状态,从而像从没有离开过一样。

每个任务都有属于自己的TSS,而TR寄存器保存着当前正在执行的任务的TSS的段选择子和基地址以及偏移量。
在执行任务A时,TR寄存器保存着任务A的TSS的段选择子和基地址。当处理器从任务A切换到任务B时,处理器执行如下操作

  1. 从TR中获取任务A的TSS段基地址
  2. 将任务A的各种状态存在任务A的TSS中
  3. 通过任务B的选择子或任务门获得任务B的TSS段选择子和基地址
  4. 将任务B的TSS段选择子和基地址存在TR寄存器中
  5. 将任务B的TSS段中的各种信息赋值给相应寄存器

TR寄存器结果如下

IA-32 Intel手册学习笔记(三)任务切换相关推荐

  1. IA-32 Intel手册学习笔记(二)保护模式下的内存管理

    内存管理概述(Memory Management Overview) Inter体系结构的内存管理可分为两部分:分段和分页. 分段提供了一种机制,这种机制可以为每个程序或者任务提供单独的代码.数据和栈 ...

  2. IA-32 Intel手册学习笔记(一)系统架构概述

    IA-32系统级架构是由寄存器.数据结构.指令组成.用来支持系统级别的操作,比如内存管理,终端和异常处理,任务管理和多处理器控制等.可以看出架构的这些部分和操作系统联系非常紧密,自然而然为操作系统提供 ...

  3. Intel VT学习笔记(三)—— VMCS(上)

    Intel VT学习笔记(三)-- VMCS(上) 要点回顾 VMCS 设置字段 错误排查 Fields Host-State Area VM-Control Fields 代码实现 参考资料 要点回 ...

  4. Intel VT学习笔记(七)—— EPT物理地址转换

    Intel VT学习笔记(七)-- EPT物理地址转换 要点回顾 EPT 支持检测 9-9-9-9-12分页 实验:EPT物理地址转换 参考资料 要点回顾 在上一篇中,已经初步实现了最小VT框架,但实 ...

  5. Intel VT学习笔记(二)—— VMXEVMXON

    Intel VT学习笔记(二)-- VMXE&VMXON VT生命周期 VMXE VMXON 准备工作 VMXON region 代码实现 参考资料 VT生命周期 描述: 软件通过执行VMXO ...

  6. Intel VT学习笔记(六)—— VM-Exit Handler

    Intel VT学习笔记(六)-- VM-Exit Handler Reutrn To DriverEntry VM-Exit Handler External interrupt I/O instr ...

  7. Intel VT学习笔记(四)—— VMCS(下)

    Intel VT学习笔记(四)-- VMCS(下) 要点回顾 VM-Exit Information Guest state fields 代码实现 参考资料 要点回顾 在上一篇中,我们了解了如何设置 ...

  8. Intel VT学习笔记(九)—— EPT应用示例

    Intel VT学习笔记(九)-- EPT应用示例 内存保护 EPT violation 代码实现 参考资料 内存保护 描述:尝试使用EPT将一块特定的物理内存保护起来. 先来选择一块物理地址,那么这 ...

  9. Intel VT学习笔记(五)—— 调试技巧

    Intel VT学习笔记(五)-- 调试技巧 要点回顾 INT 3失效 调试技巧 参考资料 要点回顾 在上一篇中,我们主要学习了如何填写Guest state fields的各项字段,以及如何对错误码 ...

最新文章

  1. MySQL01-安装mysql数据库
  2. reporting services 导出pdf格式优化
  3. Unix Domain Socket 域套接字实现
  4. 转:Ubuntu 开机加载路由设置
  5. 线性筛选素数法(O(n)复杂度)
  6. 真正的取真实IP地址及利弊Asp.net
  7. 剑指offer_04
  8. leetcode第 46 场双周赛
  9. linux wine 性能,Wine 1.9.16 发布,改善 GDI 性能
  10. (转)Hibernate事务管理
  11. i java 字节码_用java字节码解释i++和++i
  12. Spark utils —— 设置日志级别
  13. Ubuntu下使用VI编辑文件必知的常用命令
  14. Android lollipop 更新问题
  15. 【数据挖掘】数据挖掘总结 ( 模式挖掘 | Apriori 算法 | 支持度 | 置信度 | 关联规则 ) ★★
  16. PVE安装Linux提示:error: /vmlinuz has invalid signature.
  17. RedisCrawlSpider爬取当当图书信息
  18. Go (Golang) 工具之单元测试 go-junit-report | go的单元测试
  19. 学计算机基础微课视频教程,计算机基础教学对微课的应用
  20. 初学 Click 路由器

热门文章

  1. Java黑皮书课后题第4章:*4.17(一个月的天数)编写一个程序,提示用户输入一个年份和一个月份名称的前3个字母(第一个字母使用大写形式),显示该月中的天数。如果月份非法则显示出错信息
  2. THUSC2019游记
  3. JavaScript event loop事件循环 macrotask与microtask
  4. 002---tcp/ip五层详解
  5. 简述systemd的新特性及unit常见类型分析、使用systemd管理编译安装的nginx
  6. 图解集合8:红黑树的移除节点操作
  7. HTML 常用标签演示
  8. Excel 文件读取
  9. CodeForces 361B Levko and Permutation
  10. Android的基本常用的短信操作