《操作系统30天》-合川秀实-学习日志day15+16

终于讲到多任务啦~这个学期的课程也要结束了,最后是一个对之前学过的大设计,利用学到的图层知识和字体输入、定时器等,制作一个真正的操作系统!

一、任务切换

  • Cpu处理多任务的原理:实际上是通过调度在不同的时间运行不同的任务,通过快速切换任务(CPU越快切换越快,用户体验越好)实现视觉上的多任务同步。
    在这里插入图片描述
  • 任务切换指令:CPU把寄存器的值写入内存,再次切换回来就从中断的地方继续运行。引入“任务状态段”—TSS,我们使用32位版本
    在这里插入图片描述
    其中EIP寄存器记录CPU下一条指令的地址,每执行一次++。其他寄存器的值不太重要,这两个要设置:
Ldtr=0;
Iomap=0x40000000

插入TSS博客知识:
在这里插入图片描述
任务寄存器tr保存 16 位的段选择子、32 位基地址、16 位段界限和当前任务的 TSS属性。它引用 GDT 中的 TSS 描述符。基地址指明 TSS 的第一个字节(字节 0)的线性地址,段界限确定 TSS 的字节个数。TR寄存器包含了当前正在CPU运行的进程的TSSD(任务段描述符)选择符。也包含了两个隐藏的非编程域:TSSD的base和limit域。通过这种方式处理器就能直接对TSS寻址,而不用从GDT中索引TSS的地址:
TR寄存器---->GDT中的TSS描述符---->硬件上下文的具体数据。
任务切换中cpu会把当前寄存器的数据保存到当前(旧的)tr寄存器所指向的tss数据结构里,然后把新的tss数据复制到当前寄存器里。这些操作是通过cpu的硬件实现的。
原文:https://blog.csdn.net/applenob/article/details/20151067
在这里插入图片描述
在这里插入图片描述
注册到GDT(全局段号记录表)
在这里插入图片描述
…(设定寄存器为0)
规定向TR寄存器赋值时必须把GDT编号8,存值指令:load_tr(38);(用汇编)

_load_tr:		; void load_tr(int tr);
		LTR		[ESP+4]			; tr
		RET
Far跳转指令
_taskswitch3:	; void taskswitch3(void);
		JMP		3*8:0
		RET
_taskswitch4:	; void taskswitch4(void);
		JMP		4*8:0
		RET

定义寄存器的值:tss_b.esp = task_b_esp;任务B的main地址(制作io_hlt())

	task_b_esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
	tss_b.eip = (int) &task_b_main;
	tss_b.eflags = 0x00000202; /* IF = 1; */

切换任务:10秒之后切换到B任务,5秒后再换A
在这里插入图片描述
B-> Main
在这里插入图片描述
在这里插入图片描述

二、简单的多任务

  • 解决任务切换麻烦的问题
_farjmp:		; void farjmp(int eip, int cs);
		JMP		FAR	[ESP+4]				; eip, cs
		RET

这个函数实现farjmp跳转(重点部分!!)

Taskswitch3();-> farjmp(0,3*8);
Taskswitch4();-> farjmp(0,4*8);

缩短切换任务时间:timer_ts=0.02s为切换时间
在这里插入图片描述
跟光标闪烁原理一样,每次切换之后重新设定为0.02s,切换成果通过B任务的显示查看,利用同一内存地址,共享图层sht_back : *((int *) 0x0fec) = (int) sht_back;
在B的main中定义同一地址:sht_back = (struct SHEET )*((int *) 0x0fec);

三、优化速度

  1. 由于以上做法每计数1次就刷新一次,速度变慢,所以改成0.01s显示一次
    在这里插入图片描述
    用栈代替地址传递sht_back
task_b_esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
*((int *) (task_b_esp + 4)) = (int) sht_back;

这个-8了解一下,task_b_esp=0x01243ff8,写入sht_back地址就是task_b_esp+4:
在这里插入图片描述
在A,B任务中都没有return,返回的是[ESP]的值,如果里面的值合适就可以返回,如果是一个错误的地址,那程序就乱套了。(木马来源)
2. 测试改进
一秒输出一次比较,性能比之前差3倍,删除每次输出值,优化到2.1倍。
3. 多任务进阶(知识点太多,利用流程图来总结)
在这里插入图片描述

四、任务管理、休眠

作者对多任务的想法(引发很多改进):
在这里插入图片描述

  1. 类似timectl一样定义了TASKCTL-(相当于TIMECTL),TASK-(相当于TIMER)
    在这里插入图片描述
    LEVEL与任务优先级有关,第六点讲。
    作者创建了mtask.c文件,用来存放各种任务处理函数。
    • 创建函数:task_init(struct MEMMAN *memman):返回一个内存地址,说明正在运行这个程序变成一个任务了,初始化:flag=2(表示活动中),running=1表示只有一个任务等等设置.
    • 初始化函数:task_alloc(void):设置没有在使用的任务的寄存器的值(随意)
      运行函数:task_run(struct TASK *task):falg=2,running++,当前运行task,把task放在tasks末尾
    • 切换函数:task_switch(void):总任务大于2才切换,使用循环切换。
    • Bootpack.c:创建task_b初始化
      休眠:把一个任务从tasks中删除,可通过task_run唤醒
      Task_sleep(struct TASK* task)
      在这里插入图片描述
      当FIFO写入数据的时候将任务唤醒:
      在这里插入图片描述
      Fifo32_init(…,struct TASK *task)中唤醒任务fifo->task=task;
      Fifo32_put()中判断任务是否需要唤醒(fifo->task)如果处于休眠就唤醒
      在HariMain中修改:
      在这里插入图片描述
      先禁用唤醒功能,当FIFO为空时,任务A执行task_sleep代替之前的HLT,task_b不用唤醒
      在这里插入图片描述
      Task_B:
      在这里插入图片描述

五、增加窗口

添加B0-B2窗口(计数)
在这里插入图片描述
后面的设置同上,只是在make_window8的时候添加一个act变量,为1时颜色不变,为0时,窗口标题变为灰色
在这里插入图片描述

六、任务优先

修改任务切换间隔,可以实现最大10倍差异。在结构体中定义了优先级:priority

  • 在task_init中定义最开始的任务切换时间为0.02s
  • 在task_run(struct TASK *task ,int priority)通过传参数设定优先级,如果>0就设定
  • 在task_switchz设定定时器时,应用priority的值,在farjmp之前判断任务数量是否在2个以上。
  • Fifo.c:将任务唤醒不改变其优先级,直接设置为0就可以了。Task_run(fifo->task,0)
  • 改写bootpack.c:task_run(task_b[i],i+1);
    继续优化:框架是创建几个TASKCTL
    在这里插入图片描述
    只要最上面的level0中,就完全忽略下面两个的任务。当level0中的任务全部休眠或者下降时,才轮到level1。
    实际是只在TASKCTL中创建多个tasks[],每个level最多允许100个任务,总共10个level
  • Task_now:用来返回当前活动的struct TASK
  • Task_add:向TASKLEVEL中添加一个任务
  • Task_remove:从TASKLEVEL中删除一个任务(类似task_sleep)
  • Task_switchsub:决定切换到那个level
  • Task_init:定义任务设置,最高级的level=0
  • task_run(struct TASK *task, int level, int priority):在参数中指定LEVEL,如果启动了一个比现在活动的更高级的LEVEL,那么下次切换的时候就要切换到该LEVEL的那个任务中
    在这里插入图片描述
  • task_sleep(struct TASK *task):休眠传入的task,如果自己休眠进行任务切换
  • void task_switch(void):新增lv_change不为0的处理,如果不为0说明要切换LEVEL
    改写FIFO.c在task_run的传参中添加level=0。
    Bootpack中把A设为level1,B0-B2设为level2,A忙碌时就不会切换到B任务。

多任务完成之后,就是自己的设计了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值