[自制简单操作系统] 8、多任务(三)——多窗口与优先级

简介:


 

前言

>_<" 上一节已经实现了简单的多任务,而且还写了任务挂起函数,用来加快处理~这一节在上面的基础上增加多个窗口,然后又在优先级上面设计了一种分级的优先级模式~

 

一、效果展示

>_<" 如图产生了4个窗口,除了task_a窗口另外窗口是显示1s中的数数。

>_<" 这里的优先级模式是:有优先级较高的层里面有任务时,优先级低的层内的所有任务将会被屏蔽,只有该优先级高的层里面的任务才能进行任务切换~,像本例程是 把任务A是LEVEL1,优先级2;其他3个B任务分别是LEVEL2,优先级分别为1,2,3.这里的优先级是中断时间,优先级1即该任务的中断时间为 0.01s

  

 

二、代码说明

>_<" 在bootpack.h里有保存任务状态段信息的结构体TSS32,然后有任务结构体TASK,接下来是LEVEL的结构体,最后一个结构体是负责管理所有的任务~

复制代码
 1 /* mtask.c 任务切换相关*/
 2 #define MAX_TASKS                    1000   /* 最大任务数量 */
 3 #define TASK_GDT0                    3             /* 定义从GDT的几号开始分配给TSS */
 4 #define MAX_TASKS_LV    100        //每个level最多100个任务
 5 #define MAX_TASKLEVELS    10             //最多10个level
 6 
 7 struct TSS32 {//task status segment 任务状态段
 8     int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;//保存的不是寄存器的数据,而是与任务设置相关的信息,在执行任务切换的时候这些成员不会被写入(backlink除外,某些情况下会被写入)
 9     int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;//32位寄存器
10     int es, cs, ss, ds, fs, gs;//16位寄存器
11     int ldtr, iomap;//有关任务设置部分
12 };
13 struct TASK {
14     int sel, flags; /* sel用来存放GDT的编号 */
15     int level, priority;
16     struct TSS32 tss;
17 };
18 struct TASKLEVEL {
19     int running; /* 正在运行的任务量数 */
20     int now; /* 这个变量用来记录当前正在运行的任务是哪一个 */
21     struct TASK *tasks[MAX_TASKS_LV];
22 };
23 struct TASKCTL {
24     int now_lv; /* 正在运行的level */
25     char lv_change; /* 在下次任务切换时是否需要改变LEVEL */
26     struct TASKLEVEL level[MAX_TASKLEVELS];//最多10个level
27     struct TASK tasks0[MAX_TASKS];
28 };
29 extern struct TIMER *task_timer;
30 struct TASK *task_init(struct MEMMAN *memman);//初始化任务控制
31 struct TASK *task_alloc(void);//分配一个任务
32 void task_run(struct TASK *task, int level, int priority);//设置一个任务的LEVEL和优先级
33 void task_switch(void);//如果LEVEL改变了要改变当前的LEVEL然后从当前的LEVEL中找到当前任务进行切换
34 void task_sleep(struct TASK *task);//删除任务的时候要考虑LEVEL的变化~
复制代码

>_<" 在初始化里面主要多了把所有LEVEL的running(即:正在运行的任务数)置0,now(即:当前正在执行的任务的标号)置0,然后分配一个任务设置level和优先级,并加入level。其中第10行是用来设置任务切换时决定接下来切换到哪个LEVEL。接下来,分配一个时间并给它设置~

复制代码
 1 for (i = 0; i < MAX_TASKLEVELS; i++) {//把每一层的level全都设置为0
 2         taskctl->level[i].running = 0;
 3         taskctl->level[i].now = 0;
 4 }
 5 task = task_alloc();
 6 task->flags = 2; /* 活动中标志 */
 7 task->priority = 2; //任务优先级//0.02s定时器
 8 task->level = 0;    /* 第0层 */
 9 task_add(task);        //加入level中
10 task_switchsub();    /* 用来任务切换时决定接下来切换到哪个LEVEL */
11 load_tr(task->sel);
12 //向TR寄存器写入这个值,因为刚才把当前运行任务的GDT定义为3号,TR寄存器是让CPU记住当前正在运行哪一个任务
13 //每当进行任务切换时,TR寄存器的值也会自动变换,task register
14 //每次给TR赋值的时候,必须把GDT的编号乘以8
15 task_timer = timer_alloc();
16 timer_settime(task_timer, task->priority);
复制代码

>_<" 在没有改变之前,task_run中下一个要切换的任务是固定不变的,不过现在就不同了,如果本次task_run启动一个比当前活动中的任务LEVEL更高的任务,那么下次任务切换时,就得无条件的切换到更高优先级的LEVEL中。此外,如果当前任务中的LEVEL被下调,那么就得把其他LEVEL的有先任务放在前面。综上所述:我们需要再下次切换时先检查LEVEL,因此将lv_change置为1。

复制代码
 1 void task_run(struct TASK *task, int level, int priority)
 2 {
 3     if (level < 0) {
 4         level = task->level; /* 不改变level */
 5     }
 6     if (priority > 0) {
 7         task->priority = priority;
 8     }
 9 
10     if (task->flags == 2 && task->level != level) { /* 改变活动中的LEVEL */
11         task_remove(task); /* 这里执行之后flag的值会变为1,于是下面的语句也会被执行 */
12     }
13     if (task->flags != 2) {
14         /* 从休眠状态唤醒 */
15         task->level = level;
16         task_add(task);
17     }
18 
19     taskctl->lv_change = 1; /* 下次切换任务时检查LEVEL */
20     return;
21 }
复制代码

>_<" 所以在任务切换里,如果上面的LEVEL变化了,就要把第10~11行进行当前level的设置,下面就是很正常的切换了~

复制代码
 1 void task_switch(void)
 2 {
 3     struct TASKLEVEL *tl = &taskctl->level[taskctl->now_lv];//当前任务的LEVEL
 4     struct TASK *new_task, *now_task = tl->tasks[tl->now];
 5     tl->now++;
 6     if (tl->now == tl->running) {
 7         tl->now = 0;
 8     }
 9     if (taskctl->lv_change != 0) {//LEVEL之间变换了
10         task_switchsub();//用来在任务时决定接下来切换到哪个LEVEL,直接从头开始找,找到第一个LEVEL中有任务的返回
11         tl = &taskctl->level[taskctl->now_lv];
12     }
13     new_task = tl->tasks[tl->now];
14     timer_settime(task_timer, new_task->priority);
15     if (new_task != now_task) {
16         farjmp(0, new_task->sel);
17     }
18     return;
19 }
复制代码

>_<" 下面的任务挂起也比较简单了~

复制代码
 1 void task_sleep(struct TASK *task)
 2 {
 3     struct TASK *now_task;
 4     if (task->flags == 2) {
 5         /* 如果处于活动状态 */
 6         now_task = task_now();
 7         task_remove(task); /* 执行此语句的话,flags将被置为1 remove其实就是从数组中删除一个*/
 8         if (task == now_task) {
 9             /* 如果让自己休眠需要进行任务切换 */
10             task_switchsub();
11             now_task = task_now(); /* 在设定后获取当前任务的值 */
12             farjmp(0, now_task->sel);
13         }
14     }
15     return;
16 }
复制代码

>_<" 在main函数里分别对4个窗口的任务做如下设置

1 task_a = task_init(memman);//初始化任务a//初始化任务管理器,task_init会返回自己的构造地址,我们将这个地址存入fifo.task
2 fifo.task = task_a;//可以自动管理,待唤醒的task(//记录休眠任务名)
3 task_run(task_a, 1, 2);//将任务A的LEVEL设置为1,优先级2,B的3个任务LEVEL是2,所以优先级低

1 task_run(task_b[i], 2, i + 1);;//启动任务,LEVEL2,优先级1,2,3 

 

三、相关链接

没有加入优先级,只是用平均分配的模式的多窗口链接13c:http://pan.baidu.com/s/1nt4w6RB

加入LEVEL模式的优先级时的多窗口链接13e:http://pan.baidu.com/s/1eQw3sQY




本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/3995814.html,如需转载请自行联系原作者

相关文章
|
12天前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
1月前
|
算法 调度
深入理解操作系统:进程调度与优先级反转问题
【9月更文挑战第36天】操作系统是计算机科学中的核心概念,它管理着计算机的硬件资源和软件进程。在多任务处理环境中,进程调度是保证系统高效运行的关键机制之一。本文将探讨进程调度的基本概念、调度算法以及它们如何影响系统性能。同时,我们还将讨论优先级反转问题,这是一个在实时系统中常见的问题,它可能导致系统响应时间不可预测。通过分析优先级反转的原因和解决方案,我们可以更好地理解操作系统的设计和优化策略。
|
1月前
|
iOS开发 MacOS
MacOS环境-手写操作系统-36-Tab键切换窗口
MacOS环境-手写操作系统-36-Tab键切换窗口
44 1
|
2月前
|
存储 算法 前端开发
深入理解操作系统:进程调度与优先级队列算法
【9月更文挑战第25天】在操作系统的复杂世界中,进程调度是维持系统稳定运行的核心机制之一。本文将深入探讨进程调度的基本概念,分析不同的进程调度算法,并着重介绍优先级队列算法的原理和实现。通过简洁明了的语言,我们将一起探索如何优化进程调度,提高操作系统的效率和响应速度。无论你是计算机科学的初学者还是希望深化理解的专业人士,这篇文章都将为你提供有价值的见解。
|
2月前
|
安全 Unix Linux
Unix是一个多用户、多任务的操作系统
Unix是一个多用户、多任务的操作系统
164 3
|
2月前
|
算法 调度
深入理解操作系统:进程调度与优先级反转
【9月更文挑战第21天】在操作系统的心脏跳动着的,是进程调度器。它决定了哪个进程运行,何时运行,以及如何优雅地共享CPU资源。本文将通过浅显易懂的语言和直观的代码示例,探索进程调度的奥秘,揭示优先级反转问题及其解决方案,带领读者领略操作系统中这一精妙绝伦的设计。
|
1月前
|
iOS开发 MacOS
MacOS环境-手写操作系统-37-切换窗口 键盘输入
MacOS环境-手写操作系统-37-切换窗口 键盘输入
40 0
|
1月前
|
存储 算法 调度
MacOS环境-手写操作系统-34-进程优先级
MacOS环境-手写操作系统-34-进程优先级
18 0
|
1月前
|
存储 iOS开发 MacOS
MacOS环境-手写操作系统-33-多任务多窗口
MacOS环境-手写操作系统-33-多任务多窗口
35 0
|
2月前
|
机器学习/深度学习 人工智能 算法
操作系统的未来:从多任务到深度学习的演变之路
本文将探讨操作系统如何从处理简单多任务发展到支持复杂的深度学习任务。我们将分析现代操作系统面临的新挑战,以及它们如何适应人工智能和大数据时代的要求。文章不仅回顾过去,也展望未来,思考操作系统在技术演进中的角色和方向。
59 3