| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 【操作系统】30天自制操作系统--(14)多任务1 -> 正文阅读 |
|
[游戏开发]【操作系统】30天自制操作系统--(14)多任务1 |
????????本章开始多任务的设计。 一 多任务的说明????????多任务(multitask),指的是操作系统中,多个应用程序同时运行的状态。然而,对于单核CPU来说,同一个瞬间只能处理一个事情,不能做到左右互搏、一心二用的效果,那只能通过快速切换运行任务,来实现这种所谓的多任务状态: ????????在一般的操作系统中,这个切换动作每0.01-0.03秒进行一次(这样CPU大概只有1%的处理能力消耗在任务切换上,可以忽略不计)。这个切换时间不能太慢(会让人感觉到程序卡顿)、也不能太快(消耗CPU的处理能力,功夫都花在切换上面,没时间处理正事了) 。 二 实现任务切换? ? ? ? 实现任务的切换,有两个步骤: ????????(1)将TASK1有关寄存器的值写入到内存中; ????????(2)将运行TASK2需要的值从内存中读出到寄存器中; ? ? ? ? 每个任务包含的状态可以归纳为“任务状态段”(Task Status Segment,简称TSS)结构体中:
? ? ? ? TSS总计包含26个int成员(104字节),成员的内容主要是一些寄存器,具体可以参考【操作系统】CPU寄存器详解,这边主要关注一下eip指令寄存器( 指令寄存器可以说是CPU中最最重要的寄存器了,它指向了下一条要执行的指令所存放的地址,CPU的工作其实就是不断取出它指向的指令,然后执行这条指令,同时指令寄存器继续指向下面一条指令,如此不断重复,这就是CPU工作的基本日常) ????????对指令寄存器赋值(MOV EIP,0x1234),就相当于0x1234地址的指令,也就类似于汇编中的JMP 0x1234实现的效果。对任务实现切换,本质上就是从一个指令执行地址跳转到另一个指令的执行地址,这边还得用JMP指令,JMP指令又分为两种模式(near模式、far模式): ????????如果一条 JMP 指令所指定的目标地段不是可执行的代码,而是 TSS 的话,CPU 就不会执行通常的改写 EIP 和 CS 操作,而是将这条指令理解为任务切换,换句话说,TSS 里面就是用来执行任务切换的代码。 ? ? ? ? 根据上面的思路,按照下面的步骤就可以进行任务切换了: 【1】首先创建两个TSS:任务A的TSS和任务B的TSS。
【2】向他们的ldtr和iomap赋值:
【3】将他们两个在GDT中注册(这边可以参考一下【操作系统】30天自制操作系统--(4)显示字体(汉字)以及GDT/IDT中对于段1和段2的GDT注册):
【4】赋值TR寄存器(任务寄存器,存储当前正在运行哪一个任务),对它的赋值必须把GDT的编号乘以8,且对TR寄存器的操作必须在汇编的层面完成:
【5】光改变TR的值还不能任务切换,必须执行far模式的跳转指令才行:
【6】上面完成了从tss_a、tss_b的注册和跳转,这边还需要准备一下tss_b的初始化和执行程序,不然跳转到一个空地址上也不顶用: ? ? ? ? 初始化如下:
? ? ? ? 任务b的执行操作如下(定时5s之后,返回任务a):
【7】主函数中10s超时缓存处理中执行跳转(任务a---->任务b),实现10s之后跳转任务b:
? ? ? ? 综上,便实现了一个简单的多任务操作,程序运行10s之后光标停止闪烁、鼠标键盘也失效—(任务a---->任务b成功!)。再隔了5s之后,光标恢复正常,刚鼠标键盘没反应的时候存进缓存的数据也一股脑全部冒了出来(任务b---->任务a成功!)。 三 多任务操作优化【1】优化点一:重写一个farjump函数来替代原来的taskswitch3、taskswitch4:
? ? ? ? 同时在任务a和任务b中,分别准备一个timer变量叫做timer_ts(task switch),以便每隔 0.02s 切换一次:
【2】任务b中增加打印来显示确实任务切换了过来:
【3】上面任务b的操作,每计一个数都会打印,这个伴随有操作内存的操作,过于频繁地执行会是程序变慢,处理办法是设置定时器,达到超时才会执行打印:
四 多任务操作进阶? ? ? ? 截至目前,多任务的一些基本的切换操作已经具备,但是设想一下这个场景,比如说程序切换到任务b,但在任务b运行的过程中程序挂死,那么任务b就不会切换回其他的任务,这样单个任务异常,会使得整个程序挂死,这样会影响到程序的稳定性。 ? ? ? ? 解决办法是,将跳转的逻辑封装之后从HariMain与task_b_main中抽离出来,放到定时器中断inthandler20中(关于该中断的描述参考【操作系统】30天自制操作系统--(11)定时器1),定时器中断中检查是否是多任务定时器,如果是,则直接进行切换,这样就避免了各个子任务异常对于程序整体的影响: 【1】封装子任务切换逻辑 mt_taskswitch:
【2】定时器中断 inthandler20 中调用 mt_taskswitch(这边在中断的尾巴调用的原因在于:调用 mt_taskswitch() 进行任务切换的时候,即便中断处理还没有完成,IF(interrupt flag) 也有可能被重置为 1 (因为任务切换时同时也会切换 EFLAGS),而中断处理还没完成的时候产生中断显然是不允许的):
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/17 0:49:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |