一、7.协同式任务切换与抢占式任务切换

image-20230804143704820

使用TSS来在任务切换时保护现场和恢复现场

image-20230804144504435

内核任务:单纯由内核组成的任务,和其他用户程序组成其他任务

内核任务的创建

;为内核任务创建任务控制块TCB
mov ecx, 0x46
call sys_routine_seg_sel:allocate_memory
call append_to_tcb_link ;将此TCB添加到TCB链上
mov esi, ecx;为内核任务的TSS分配内存空间
mov ecx, 104 ;为内核任务的TSS分配内存
call sys_routine_seg_sel:allocate_memory
mov [es:esi+0x14], ecx ;在内核TCB中保存TSS基地址;在内核任务的TSS中设置必要的项目 
mov word [es:ecx+96],0             ;没有LDT。处理器允许没有LDT的任务。
mov word [es:ecx+102],103          ;没有I/O许可位图。0特权级事实上不需要。
mov word [es:ecx+0],0              ;反向链=0,不使用硬件任务切换,不产生任务链
mov dword [es:ecx+28],0            ;登记CR3(PDBR)
mov word [es:ecx+100],0            ;T=0;不需要0、1、2特权级堆栈。0特级不会向低特权级转移控制。

IO许可位图:

image-20230804152320777

当任务的CPL特权级高于(数值小于)他的EFLAGS中的IOPL字段,那么这个任务可以访问任何硬件端口,0特权级可访问任何硬件端口

修改IOPL:需要先把EFLAGS/FLAGS压栈,在栈中修改,然后出栈

image-20230804153010489

在16位操作尺寸下也可以压入32位的EFLAGS,只需要使用PUSHFD翻转操作数尺寸即可,但在32位操作尺寸下PUSHF和PUSHFD作用相同

POPF同理

PUSHF/PUSHFD和POPF/POPFD的执行不受特权级限制,但是标志寄存器压栈后IOPL字段的读写状态受特权级影响,若CPL不为0,则栈中的IOPL类似只读状态

image-20230804155508870

当然也不是说一旦CPL特权级低于IOPL,所有硬件端口就禁止访问

image-20230804160548500

image-20230804160514454

TSS描述符中的段界限包含了IO许可位映射区的大小

任务切换

image-20230804162532218

协同式任务切换

		;创建内核任务的TSS描述符,并安装到GDT中 mov eax,ecx                        ;TSS的起始线性地址mov ebx,103                        ;段长度(界限)mov ecx,0x00408900                 ;TSS描述符,特权级0call sys_routine_seg_sel:make_seg_descriptorcall sys_routine_seg_sel:set_up_gdt_descriptormov [prgman_tss+0x04],cx           ;保存程序管理器的TSS描述符选择子 ;任务寄存器TR中的内容是任务存在的标志,该内容也决定了当前任务是谁。;下面的指令为当前正在执行的0特权级任务“程序管理器”后补手续(TSS)。ltr cx        ;现在可认为内核任务正执行中

创建用户程序

		mov ecx,0x46call sys_routine_seg_sel:allocate_memorycall append_to_tcb_link            ;将此TCB添加到TCB链中 push dword 50                      ;用户程序位于逻辑50扇区push ecx                           ;压入任务控制块起始线性地址 call load_relocate_program ;主动发起任务切换     
initiate_task_switch: ;主动发起任务切换pushadpush dspush esmov eax, core_data_seg_selmov es, eaxmov eax, mem_0_4_gb_seg_selmov ds, eaxmov eax, [es:tcb_chain]; 搜索状态为忙(当前任务)的节点.b0:cmp word [eax+0x04], 0xffffcmove esi, eaxjz .b1;从当前节点继续搜索就绪任务的节点.b1:mov ebx, [eax]or ebx, ebxjz .b2 ;到表尾也没找到,就从头找cmp word [ebx+0x04], 0x0000cmove edi, ebx ;找到就绪节点,edi=节点线性地址jz .b3mov eax, ebxjmp .b1.b2:mov ebx, [es:tcb_chain].b20:cmp word [ebx+0x04], 0x0000cmove edi, ebxjz .b3mov ebx, [ebx]or ebx, ebxjz .return ;表中不存在空闲任务,返回jmp .b20;就绪任务的节点已找到,准备切换.b3:not word [esi+0x04] ;将忙状态的节点改为就绪not word [edi+0x04] ;将就绪节点改为忙jmp far [edi+0x14] ;任务切换.return:pop espop dspopadretf
;用户任务进行任务切换
call far [fs:InitTaskSwitch];用户任务退出
call far [fs:TerminateProgram]
terminate_current_task: ;终止当前任务;注意,执行此例程时,当前任务仍在运行中。此例程其实也是当前任务的一部分 mov eax, core_data_seg_selmov es, eaxmov eax, mem_0_4_gb_seg_selmov ds, eaxmov eax, [es:tcb_chain] ;eax=首节点的线性地址;搜索状态为忙(当前任务)的节点.s0:cmp word [eax+0x04]jz .sl ;找到忙节点,eax=节点的线性地址mov eax, [eax] jmp .s0;将状态为忙的节点改成终止状态.s1:mov word [eax+0x04], 0x3333;搜索就绪状态的任务mov ebx, [es:tcb_chain] ;ebx=链表首节点线性地址.s2:cmp word [ebx+0x04], 0x0000jz .s3 ;已找到就绪节点,ebx=节点的线性地址mov ebx, [ebx]jmp .s2;就绪任务的节点已经找到,准备切换到该任务.s3:not word [ebx+0x04]jmp far [ebx+0x14]

抢占式任务切换

抢占式任务切换需要依赖硬件中断

中断与异常是并列关系

image-20230804201353006

异常根据发生原因可分为:

image-20230804201741720

异常根据性质可分为:
image-20230804201939590

image-20230804205133862

实模式下直接访问IVT获取中断处理代码地址

保护模式下需要获取描述符

image-20230804204551718

image-20230804204753037

image-20230804205735725

image-20230804205749878

创建并安装中断门

general_interrupt_handler:                  ;通用的中断处理过程push eaxmov al,0x20                        ;中断结束命令EOI out 0xa0,al                        ;向从片发送 out 0x20,al                        ;向主片发送pop eaxiretd;-------------------------------------------------------------------------------
general_exception_handler:                  ;通用的异常处理过程mov ebx,excep_msgcall flat_4gb_code_seg_sel:put_stringhlt
;-------------------------------------------------------------------------------
rtm_0x70_interrupt_handle:                  ;实时时钟中断处理过程pushadmov al,0x20                        ;中断结束命令EOIout 0xa0,al                        ;向8259A从片发送out 0x20,al                        ;向8259A主片发送mov al,0x0c                        ;寄存器C的索引。且开放NMIout 0x70,alin al,0x71                         ;读一下RTC的寄存器C,否则只发生一次中断;此处不考虑闹钟和周期性中断的情况call sys_routine_seg_sel:initiate_task_switch ;请求任务切换popadiretd
		mov ecx, core_data_seg_selmov ds, ecx ;ds指向核心数据段mov ecx, mem_0_4_gb_seg_selmov es, ecx ;es指向4G数据段;创建中断描述符表IDT;其余为保留或硬件使用的中断向量mov eax,general_exception_handler  ;公共异常处理代码在段内偏移地址mov bx,flat_4gb_code_seg_sel       ;代码所在段的选择子mov cx,0x8e00                      ;中断门高32位部分的低16位,0特权级call flat_4gb_code_seg_sel:make_gate_descriptor ;构建门描述符mov ebx,idt_linear_address         ;中断描述符表的线性地址xor esi,esi.idt0:mov [es:ebx+esi*8],eaxmov [es:ebx+esi*8+4],edxinc esicmp esi,19                         ;安装前20个异常中断处理过程jle .idt0;除了0~20是公共的中断门,还有32~255为为保留或硬件使用的中断向量mov eax,general_interrupt_handler  ;门代码在段内偏移地址mov bx,flat_4gb_code_seg_sel       ;门代码所在段的选择子mov cx,0x8e00                      ;32位中断门,0特权级call flat_4gb_code_seg_sel:make_gate_descriptormov ebx,idt_linear_address         ;中断描述符表的线性地址.idt1:mov [es:es:ebx+esi*8],eaxmov [es:ebx+esi*8+4],edxinc esicmp esi,255                        ;安装普通的中断处理过程jle .idt1;设置实时时钟中断处理过程mov eax,rtm_0x70_interrupt_handle  ;门代码在段内偏移地址mov bx,flat_4gb_code_seg_sel       ;门代码所在段的选择子mov cx,0x8e00                      ;32位中断门,0特权级call flat_4gb_code_seg_sel:make_gate_descriptormov ebx,idt_linear_address         ;中断描述符表的线性地址mov [es:ebx+0x70*8],eaxmov [es:ebx+0x70*8+4],edx

image-20230805085932089

加载中断描述符表寄存器IDTR

image-20230805093051632

pidt             dw  0dd  0
		;准备开放中断mov word [pidt],256*8-1            ;IDT的界限mov dword [pidt+2],idt_linear_addresslidt [pidt]                        ;加载中断描述符表寄存器IDTR

8259A主片默认使用0x08 ~ 0x0F中断向量号,但是处理器已经把0x08 ~ 0x0F设置成异常了,向量号冲突,需要重新设置

初始化命令字ICW1 ~ 4可发给主片和从片,先把ICW1发给主片的0X20和从片的0XA0,根据其内容决定让主片(0X21)和从片(0XA1)是否期待后续

image-20230805094805019

image-20230805095025403

image-20230805095510587

image-20230805095638974

 		;设置8259A中断控制器mov al,0x11out 0x20,al                        ;ICW1:边沿触发/级联方式mov al,0x20out 0x21,al                        ;ICW2:起始中断向量mov al,0x04out 0x21,al                        ;ICW3:从片级联到IR2mov al,0x01out 0x21,al                        ;ICW4:非总线缓冲,全嵌套,正常EOImov al,0x11out 0xa0,al                        ;ICW1:边沿触发/级联方式mov al,0x70out 0xa1,al                        ;ICW2:起始中断向量mov al,0x04out 0xa1,al                        ;ICW3:从片级联到IR2mov al,0x01out 0xa1,al                        ;ICW4:非总线缓冲,全嵌套,正常EOI;设置和时钟中断相关的硬件 mov al,0x0b                        ;RTC寄存器Bor al,0x80                         ;阻断NMIout 0x70,almov al,0x12                        ;设置寄存器B,禁止周期性中断,开放更out 0x71,al                        ;新结束后中断,BCD码,24小时制in al,0xa1                         ;读8259从片的IMR寄存器and al,0xfe                        ;清除bit 0(此位连接RTC)out 0xa1,al                        ;写回此寄存器mov al,0x0cout 0x70,alin al,0x71                         ;读RTC寄存器C,复位未决的中断状态sti                                ;开放硬件中断

中断和异常处理时的特权级保护:

  1. 不检查RPL
  2. 不检查门的DPL,除了int nint3into
  3. 中断描述符描述的目标代码段的特权级必须高于等于当前代码特权级

image-20230805100446208

中断和异常发生时的栈切换过程

image-20230805101307699

与任务切换类似,都是在任务的TSS中找到中断处理过程段的对应特权级的栈寄存器然后压栈各种寄存器保护现场

有些异常产生时,处理器会在栈中压入错误代码

image-20230805102150426

image-20230805102725397

image-20230805103348728

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

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

相关文章

BClinux8.6 制作openssh9.2p2 rpm升级包和升级实战

一、背景说明 BClinux8.6 安装的openssh 版本为9.3p1,经绿盟扫描,存在高危漏洞,需要升级到最新。 OpenSSH 命令注入漏洞(CVE-2020-15778) OpenSSH 安全漏洞(CVE-2023-38408) 目前官网只提供编译安装包,而BClinux8.6 为rpm方…

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测预测效果基本介绍研究内容程序设计参考资料…

Vue中,$forceUpdate()的使用

在Vue官方文档中指出,$forceUpdate具有强制刷新的作用。 那在vue框架中,如果data中有一个变量:age,修改他,页面会自动更新。 但如果data中的变量为数组或对象,我们直接去给某个对象或数组添加属性,页面是识…

antv/l7地图,鼠标滚动,页面正常滑动-- 我们忽略的deltaY

背景 在官网项目中,需要使用一个地图,展示产品的分布区域及数量。希望的交互是,鼠标放上标点,tooltip展示地点和数量等信息。鼠标滚动,则页面随着滚动。但是鼠标事件是被地图代理了的,鼠标滚动意味着地图的…

性能测试入门知识总结

目录 1.什么是性能测试? 2.为什么要进行性能测试? 3.性能测试的常见术语 4.性能测试的分类 5.性能测试如何展开? 1.什么是性能测试? 性能测试是一种测试类型,旨在确定系统的性能以衡量性能,验证或验证…

8.15锁的优化

1.锁升级(锁膨胀) 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 偏向锁:不是真的加锁,而是做了一个标记,如果有别的线程来竞争才会真的加锁,如果没有别的线程竞争就不会加锁. 轻量级锁:一个线程占领锁资源后,另一个线程通过自旋的方式反复确认锁是否被是否(这个过程比较…

RabbitMQ安装说明文档-v2.0

rabbitmq安装 说明:请使用资料里提供的CentOS-7-x86_64-DVD-1810.iso 安装虚拟机. 1. 安装依赖环境 在线安装依赖环境: yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel …

【并发专题】单例模式的线程安全(进阶理解篇)

目录 背景前置知识类加载运行全过程 单例模式的实现方式一、饿汉式基本介绍源码分析 二、懒汉式基本介绍源码分析改进 三、懒汉式单例终极解决方案(静态内部类)(推荐使用方案)基本介绍源码分析 感谢 背景 最近学习了JVM之后&…

面试题:JS如何最快的执行垃圾回收机制

因为没看见答案,所以也不知道对不对。 JavaScript 的垃圾回收机制是由 JavaScript 引擎自动管理的,通常情况下我们无法控制垃圾回收机制的执行时间和频率。 然而,我们可以采取一些优化策略来减少垃圾回收的性能开销,从而提高代码…

golang函数传参——值传递理解

做了五年的go开发,却并没有什么成长,都停留在了业务层面了。一直以为golang中函数传参,如果传的是引用类型,则是以引用传递,造成这样的误解,实在也不能怪我。我们来看一个例子,众所周知&#xf…

uniapp发布插件显示components/xxx文件没找到,插件格式不正确

uniapp发布插件显示components/xxx文件没找到,插件格式不正确 将插件文件这样一起选中,然后右键压缩成zip文件,而不是外层文件压缩

记一次 .NET某医疗器械清洗系统 卡死分析

一:背景 1. 讲故事 前段时间协助训练营里的一位朋友分析了一个程序卡死的问题,回过头来看这个案例比较经典,这篇稍微整理一下供后来者少踩坑吧。 二:WinDbg 分析 1. 为什么会卡死 因为是窗体程序,理所当然就是看主…

SQL ASNI where from group order 顺序

SQL语句执行顺序: from–>where–>group by -->having — >select --> order 第一步:from语句,选择要操作的表。 第二步:where语句,在from后的表中设置筛选条件,筛选出符合条件的记录。 …

PyTorch深度学习实战(9)——学习率优化

PyTorch深度学习实战(9)——学习率优化 0. 前言1. 学习率简介2. 梯度值、学习率和权重之间的相互作用3. 学习率优化实战3.1 学习率对缩放后的数据集的影响3.2 学习率对未缩放数据集的影响 小结系列链接 0. 前言 学习率( learning rate )是神经网络训练中…

从0到1开发go-tcp框架【4实战片— — 开发MMO之玩家聊天篇】

从0到1开发go-tcp框架【实战片— — 开发MMO】 MMO(MassiveMultiplayerOnlineGame):大型多人在线游戏(多人在线网游) 1 AOI兴趣点的算法 游戏中的坐标模型: 场景相关数值计算 ● 场景大小: 250…

解密爬虫ip是如何被识别屏蔽的

在当今信息化的时代,网络爬虫已经成为许多企业、学术机构和个人不可或缺的工具。然而,随着网站安全防护的升级,爬虫ip往往容易被识别并屏蔽,给爬虫工作增加了许多困扰。在这里,作为一家专业的爬虫ip供应商,…

2023上半年手机及数码行业分析报告(京东销售数据分析)

2023年上半年,手机市场迎来复苏,同环比来看,销量销额纷纷上涨。 而数码市场中,各个热门品类表现不一。微单相机及智能手表同比去年呈现增长态势,而笔记本电脑市场则出现下滑。 基于此现状,鲸参谋发布了20…

谈一谈Python中的装饰器

1、装饰器基础介绍 1.1 何为Python中的装饰器? Python中装饰器的定义以及用途: 装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器可以用来修改或增强函数的行为,而不需要修改函数本身…

JVM深入 —— JVM的体系架构

前言 能否真正理解JVM的底层实现原理是进阶Java技术的必由之路,Java通过JVM虚拟机的设计使得Java的延拓性更好,平台无关性是其同时兼顾移动端和服务器端开发的重要特性。在本篇文章中,荔枝将会仔细梳理JVM的体系架构和理论知识,希…

Dubbo+Zookeeper使用

说明:Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。 本文介绍Dubbo的简单使用及一些Dubbo功能特性,注册中心使用的是ZooKeeper,可在…