x86下使用硬件实现的任务切换(TSS表)---使用代码讲解

实现任务切换(使用TSS)

视频讲解可以看这一个课程

• The current program, task, or procedure executes a JMP or CALL instruction to a TSS descriptor in the GDT.

• The current program, task, or procedure executes a JMP or CALL instruction to a task-gate descriptor in the GDT or the current LDT.
这两段的意思大概是可以使用jmp或者使用call指令指向GDT或者LDT表里面的TSS描述符就可以进行跳转
GDT表讲解

所以实际使用TSS进行跳转的过程是

  1. 初始化一个TSS表
  2. 加入描述符到GDT表里面
  3. 使用jmp或call进行跳转

第一个任务需要手动告知CPU自己的TSS在哪一个描述符

TSS表

在进行任务切换的时候最重要的记录当前的状态, x86提供了一个TSS表用来记录这一个任务的状态
image.png

x86使用一个这样的结构进行保存任务的状态

这里面存放的是当前任务的状态, CPU会自动把寄存器的状态存放在这里面

这里面的SS, ESP等有多个是给不同特权级的时候使用不同的段, 在处理终中断的时候使用不同的栈

Previous Task Link: 任务的连接, 没有用到

之后是几个不同优先级的时候使用的不同的额栈, ss是栈的段寄存器

cr3记录的是页表的值(用于虚拟内存)

再往后是寄存器的信息

LDT, 记录LDT的选择子(给任务使用的GDT表)

IO图, SSP没有使用

在使用的时候可以使用一个jmp指令进行跳转

在产生中断的时候会从特权级0的位置找到栈, 之后执行中断相关的内容

需要在GDT里面使用段来记录任务的TSS, 通过GDT的描述符进行区分

image.png

TSS表在GDT里面的描述符
Base: 起始地址

Segment Limit: 界限-1

DPL: 段的访问权限, 0-3

P: 这一个段是否有效

G: 指定limit的单位是byte还是4KB

AVL: 保留

type: 段的类型

B: 忙标志

代码实现

//任务的TSS保存位置
#define TASK0_TSS_SEG           ((5 * 8))
#define TASK1_TSS_SEG           ((6 * 8))//GDT表里面加两个TSS表描述符
struct {uint16_t limit_l, base_l, basehl_attr, base_limit;}gdt_table[256] __attribute__((aligned(8))) = {....//TSS表, 由于直接使用一个数组作为TSS会导致报错,这里基地址初始化为0, 后面在C语言里面加地址[TASK0_TSS_SEG /8] = {0x68, 0, 0xe900, 0},[TASK1_TSS_SEG /8] = {0x68, 0, 0xe900, 0},
};
....
//初始化几个32位的栈, 使用模式为特权级3
uint32_t task0_dpl3_stack[1024];//用户级的栈
uint32_t task1_dpl3_stack[1024];
uint32_t task0_dpl0_stack[1024];//系统级的栈
uint32_t task1_dpl0_stack[1024];//定义一个TSS结构
//任务切换的时候栈之类的寄存器不会保存, 需要初始化设置
uint32_t task0_tss[] = {//依次填入TSS表里面的信息
};
//设置要切换的任务的栈以及任务的入口
uint32_t task1_tss[] = {//依次填入TSS表里面的信息
};.....//把表地址记录进入gdt_table[TASK0_TSS_SEG / 8].base_l = (uint16_t)(uint32_t)task0_tss;gdt_table[TASK1_TSS_SEG / 8].base_l = (uint16_t)(uint32_t)task1_tss;
  • 使用TR寄存器保存当前的任务的TSS对应的GDT位置, 需要使用汇编指令设置这一个值
	//告诉CPU正在运行的任务mov $TASK0_TSS_SEG, %axltr %ax

实际的任务切换

void task_sched(void){static int task_tss = TASK0_TSS_SEG;//选一个TSS表task_tss = (task_tss == TASK0_TSS_SEG) ? TASK1_TSS_SEG : TASK0_TSS_SEG;uint32_t addr[] = {0, task_tss};//偏移以及选择子__asm__ __volatile__("ljmpl *(%[a])"::[a]"r"(addr));
}

*() 是通过间接寻址方式访问内存中的内容。在这段代码中,*(%[a]) 表示将 %[a] 所代表的地址作为一个指针,然后访问这个指针指向的内存位置。

在远跳指令 ljmp 中,需要跳转的目标地址是通过一个指针来指定的。所以,使用 *() 来对指针进行间接寻址,以获取指针所指向的内容(即跳转目标地址),并将该地址作为参数传递给 ljmp 指令。

在这段代码中,*(%[a]) 中的 %[a] 是一个占位符,用来表示汇编代码中的输入变量 [a],即地址数组 addr 的地址。所以 *(%[a]) 表示获取 addr 数组的地址所对应的内容,即跳转的目标地址。

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

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

相关文章

并查集,真好用,一次AC不是梦!

文章目录 🚀前言🚀并查集🚀并查集的两个优化✈️路径压缩✈️按秩合并 🚀并查集代码模板 🚀前言 大家好啊!今天阿辉来给大家介绍一种简洁而优雅的数据结构——并查集,不知道各位是否了解它&…

ssh连接服务器需要子网掩码吗?

IP寻址需要同时知道IP地址和子网掩码,但是在通过ssh连接服务器时,只需要知道IP地址和端口号就可以了,ssh通讯为什么不需要子网掩码呢。在不知道子网掩码的前提下,可以正确找到IP对应的主机吗? 不需要,SSH&a…

桌面显示器应用Type-C接口

随着科技的飞速发展,桌面显示器作为我们日常工作中不可或缺的设备之一,也在不断地更新换代。其中,Type-C接口的应用成为了桌面显示器发展的一个重要趋势。那么,桌面显示器应用Type-C接口究竟有什么好处呢? 首先&#x…

职场隐私守则:关系再好也别碰这些“雷区”

在职场中,与同事建立良好的关系是非常重要的,它有助于提高工作效率、增进团队协作,并且能够为日常的工作带来便利。 然而,即便与同事的关系再亲密,也有一些隐私话题是绝对不能轻易透露的。 在与同事和领导相处时&…

文章复现 | 差异分析和PPI网络构建

原文链接:差异分析和PPI网路图绘制教程 写在前面 在原文中,作者获得285个DEG,在此推文中共获得601个DEG。小杜的猜想是标准化的水段不同的原因吧,或是其他的原因。此外,惊奇的发现发表医学类的文章在附件中都不提供相…

燃气热水器水箱的气密性测试密封方案介绍—格雷希尔快速接头

家用燃气热水器的气密性检测是保障其安全性的重要环节之一,如热水器的水箱,它的周围缠绕着一圈铜管,这圈铜管和水箱之间有数量不等的焊接点,为了保证热水器的正常运行,必须要对它们进行气密性测试。   燃气热水器水箱…

文件且目录损坏无法读取怎么办?

文件及目录损坏无法读取是计算机使用过程中的常见故障,这可能是由于多种原因导致的,例如硬件故障、文件系统错误、病毒感染或不当操作等。本文将对这一问题进行深入分析,探讨其根本原因,并提供相应的解决方法,包括数据…

Collectors.toMap使用记录

最近看到一行比较有趣的代码,他的功能就是将List转换为Map。我觉得挺有意思的,先前没遇到过,于是打算写篇文章记录一下。 public enum CodeEnum {USER("user"),AGE("age"),INTEREST("interest"),;private Str…

揭秘:一行代码搞定.Net API高并发的烦恼

高并发下的接口请求重复提交问题 在.Net开发中,我们经常遇到用户疯狂点击同一按钮,或者服务响应慢时重复发送请求,导致数据重复添加或混乱。这不仅浪费资源,更会得到错误的业务结果。如何高效解决这一普遍问题呢? 常规…

影响效果图渲染的因素有哪些?渲染100邀请码1a12

效果图对很多行业是刚需,特别是视觉行业,一张好的效果图非常重要,影响效果图渲染的因素有很多,它们是哪些呢?一起来看看吧。 1、渲染引擎 渲染引擎对效果图的渲染至关重要,目前市面上有很多渲染引擎&#x…

阅读笔记(SOFT COMPUTING 2018)Seam elimination based on Curvelet for image stitching

参考文献: Wang Z, Yang Z. Seam elimination based on Curvelet for image stitching[J]. Soft Computing, 2018: 1-16. 注:SOFT COMPUTING 大类学科小类学科Top期刊综述期刊工程技术 3区 COMPUTER SCIENCE, ARTIFICIAL INTELLIGENCE 计算机&#xf…

6.1.0 MPLS LDP动态分配

手动写静态MPLS的转发路径,不仅不方便管理,同时配置量也非常多,每台设备都需要去做配置。为了方便管理且去除繁琐的配置,就需要使用到LDP动态标签分发协议了。 标签分发协议LDP(Label Distribution Protocol&#xff…

迈向AI时代:掌握Python编程与ChatGPT的强强联手

文章目录 一、ChatGPT与Python编程的结合二、利用ChatGPT学习Python编程的优势三、如何使用ChatGPT学习Python编程四、学习技巧与建议《码上行动:用ChatGPT学会Python编程》特色内容简介作者简介目录获取方式 随着人工智能技术的飞速发展,编程已经成为了…

【漏洞复现-通达OA】通达OA report_bi存在前台SQL注入漏洞

一、漏洞简介 通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化软件,是与中国企业管理实践相结合形成的综合管理办公平台。通达OA为各行业不同规模的众多用户提供信息化管理能力,包括流程审批、行政办公、日常事务、数据统计…

Unity3D Shader 素描风格渲染管线实现详解

前言 在游戏开发中,渲染效果是非常重要的一部分,它可以直接影响游戏的视觉效果和玩家的体验。而素描风格的渲染效果是一种非常独特和有趣的风格,可以为游戏增添一种艺术氛围。在Unity3D中,可以通过编写Shader来实现素描风格的渲染…

java面试

一、java基础篇 1.接口和抽象类的区别 相似点: (1)接口和抽象类都不能被实例化 (2)实现接口或继承抽象类的普通子类都必须实现这些抽象方法 不同点: (1)抽象类可以包含普通方法…

YOLOv8 | 代码逐行解析(二) | 从yaml文件到模型定义(代码逐行注释,小白必看)

👑欢迎大家订阅我的专栏一起学习YOLO👑 一、本文介绍 本文给大家带来的是YOLOv8项目的解读,之前给大家分析了YOLOv8的项目文件分析,这一篇文章给大家带来的是模型训练从我们的yaml文件定义到模型的定义部分的讲解,我们一般只知道如何去训练模型,和配置yaml文件,但是…

STM32 学习2 库函数控制GPIO输出

STM32 学习2 库函数控制GPIO输出 一、GPIO寄存器介绍1. GPIO简介2. GPIO功能(1)模式分类(2)模式设置方法MODE[1:0]:模式控制,用于配置端口引脚的模式:CNF[1:0]:配置引脚输出速度&…

【vue+leaflet】vue项目中使用leaflet绘制室内平面图、leaflet.pm在平面图中绘制点、线、面图层(一)

效果图: 一,插件安装 npm i leaflet --save // 我的版本^1.9.4 npm i leaflet.pm --save // 我的版本^2.2.0附官网链接: leaflet官网: https://leafletjs.com/index.html leaflet.pm官网: https://www.npmjs.com/package/leaflet.pm?activeTabreadme 二,模块引入 因为我…

Android MMKV 接入+ 替换原生 SP + 原生 SP 数据迁移

背景:项目中一直使用的是原生 SP,众所周知,使用原生 SP 存在卡顿性能问题。公司的性能监控平台抓到不少原生 SP 导致的 ANR 问题: java.io.FileDescriptor.sync (FileDescriptor.java) android.os.FileUtils.sync (FileUtils.java:256) android.app.SharedPreferencesImpl.…