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,一经查实,立即删除!

相关文章

Spring Event详解

Spring Event详解 1.详细介绍2.使用场景3.注意事项4.案例分析5.代码实现6.与消息队列的区别7.SpringEvent结合线程池异步实现 1.详细介绍 Spring Event是Spring框架内建的一种发布/订阅(Publish-Subscribe)模式的实现,它允许应用内部不同组件…

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

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

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

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

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

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

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

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

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

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

【微信小程序】wxss 和 css 、wxml 和 html 区别

wxss 和 css 区别 wxss 支持小程序特有的选择器和 样式属性 scroll-into-view cover-view 等wxss 引入了 rpx 单位,可以根据屏幕宽度进行自适应,使得开发者可以更方便的处理不同尺寸屏幕的适配问题。wxss 背景图片只能引入外链,不能使用本地…

golang 获取域名 ip dns 信息

1 Go语言查找DNS A记录 A (Address) 记录是用来指定主机名(或域名)对应的IP地址记录. 用户可以将该域名下的网站服务器指向到自己的web server上. 同时也可以设置您域名的二级域名. 使用 Go 语言的标准库 net.LookupIP() 接受域名的字符串参数,返回 ne…

【零基础学习CAPL】——CAN报文的发送(LiveCounter——生命信号)

🙋‍♂️【零基础学习CAPL】系列💁‍♂️点击跳转 文章目录 1.概述2.面板创建3.系统变量创建4.CAPL实现5.效果5.1.0~15循环发送5.2.固定值发送6.全量脚本1.概述 本章主要介绍带有生命信号LiveCounter的报文发送脚本 一般报文可使用CANoe的IG模块直接发送,但存在循环冗余…

代码随想录算法训练营第三十六天|435.无重叠区间、763.划分字母区间、56.合并区间

435.无重叠区间 思路:找到删除几个区间,让题目给出的区间没有重叠部分,那么首先我们先进行排序(按照左边界排序),那么下一个区间的左边界小于上一个区间的右边界,那么这两个区间一定有重叠的部分…

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

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

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

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

Gemini API模型详细信息一览表

Gemini API模型详细信息一览表,api模型:gemini-pro\gemini-pro-vision\embedding-001\aqa VariationAttributeDescriptionGemini ProModel last updatedFebruary 2024Model codemodels/gemini-proModel capabilities Input: textOutput: textGenerates …

ubuntu linux kernel内核操作

替换linux内核 实验步骤(在root权限下进行) 1.内核编译前的准备工作 2.下载内核 4. 编译新内核 5. 内核安装 6. 安装模块 7. 生成initrd.img文件 8. 切换到/boot/grub/目录下,自动查找新内核,并添加至grub引导 9. 重启Ubantu,在previous version中选择启动新编译的内核 …

Collectors.toMap使用记录

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

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

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

vscode 命令无法执行

以管理员启动powershell 输入set-ExecutionPolicy RemoteSigned yarn : 无法加载文件 D:\node\node_global\yarn.ps1。未对文件 D:\node\node_global\yarn.ps1 进行数字签名。无法在当前系统上运行该脚本。有关运行脚本和设置执行策略的详细信息,请参阅 https:/go…

2024年华为OD机试真题-计算三叉搜索树的高度-Java-OD统一考试(C卷)

题目描述: 定义构造三叉搜索树规则如下: 每个节点都存有一个数,当插入一个新的数时,从根节点向下寻找,直到找到一个合适的空节点插入。 查找的规则是: 1. 如果数小于节点的数减去500,则将数插入节点的左子树 2. 如果数大于节点的数加上500,则将…

影响效果图渲染的因素有哪些?渲染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…