30天自制操作系统(16)
DAY16_多任务(2)
1.任务管理自动化
- 充分做好多任务机制的基础上,再利用多任务逐步完善操作系统本身。
- 如果我们想要运行三个任务的话,就必须改写mt_taskswitch的代码。如果能像当初定时器和窗口背景的做法一样更好。
struct TASKCTL *taskctl; |
- 调用task_init,会返回一个内存地址,意思是==现在正在运行的这个程序,已经变成一个任务了==。可能大家不是很能理解这个说法,在调用init之后,所有程序的运行都会被当成任务来进行管理,而调用init的这个程序,我们也要让它所属于某个任务,这样一来,通过调用任务的设置函数,就可以对任务进行各种控制,比如说修改优先级等。
2.让任务休眠
- 给每个任务==分配不同的时间==——休眠+唤醒
休眠:
void task_sleep(struct TASK *task)
{
int i;
char ts = 0;
if (task->flags == 2) { /*如果指定任务处于唤醒状态*/
if (task == taskctl->tasks[taskctl->now]) {
ts = 1; /*让自己休眠的话,稍后需要进行任务切换*/
}
/*寻找task所在的位置*/
for (i = 0; i < taskctl->running; i++) {
if (taskctl->tasks[i] == task) {
/*在这里*/
break;
}
}
taskctl->running--;
if (i < taskctl->now) {
taskctl->now--; /*需要移动成员,要相应地处理*/
}
/*移动成员*/
for (; i < taskctl->running; i++) {
taskctl->tasks[i] = taskctl->tasks[i + 1];
}
task->flags = 1; /*不工作的状态*/
if (ts != 0) {
/*任务切换*/
if (taskctl->now >= taskctl->running) {
/*如果now的值出现异常,则进行修正*/
taskctl->now = 0;
}
farjmp(0, taskctl->tasks[taskctl->now]->sel);
}
}
return;
}唤醒:
- 形成任务A、任务B0、任务B1和任务B2的格局。
- 任务B0~B2各自拥有自己的窗口,它们的功能都一样,即进行计数,这有点像在Windows中启动了一个应用程序及其2个副本的感觉。
4.设定任务优先级(1)
- 改写mtask.c、task_switch
void task_switch(void)
{
struct TASK *task;
taskctl->now++;
if (taskctl->now == taskctl->running) {
taskctl->now = 0;
}
task = taskctl->tasks[taskctl->now];
timer_settime(task_timer, task->priority);
if (taskctl->running >= 2) {
farjmp(0, task->sel);
}
return;
}
5.设定任务优先级(2)
- 在操作系统中有一些处理,即使牺牲其他任务的性能也必须要尽快完成,否则会引起用户的不满,就比如这次对鼠标的处理。对于这类任务,我们可以让它在处理结束后马上休眠,而优先级则可以设置得非常高。
- 我们需要设计一种架构,使得即便高优先级的任务同时运行,也能够区分哪个更加优先。
- 这种架构的工作原理是,最上层的LEVEL 0中只要存在哪怕一个任务,则完全忽略LEVEL 1和LEVEL 2中的任务,只在LEVEL 0的任务中进行任务切换。当LEVEL 0中的任务全部休眠,或者全部降到下层LEVEL,也就是当LEVEL 0中没有任何任务的时候,接下来开始轮到LEVEL 1中的任务进行任务切换。当LEVEL 0和LEVEL 1中都没有任务时,那就该轮到LEVEL2 出场了。
在这种架构下,只要把音乐播放任务设置在LEVEL 0中,就可以保证获得比鼠标更高的优先级。
- task_now 用于返回现在活动中的struct TASK的内存地址
struct TASK *task_now(void)
{
struct TASKLEVEL *tl = &taskctl->level[taskctl->now_lv];
return tl->tasks[tl->now];
} - task_add,用来向struct TASKLEVEL中添加一个任务
void task_add(struct TASK *task)
{
struct TASKLEVEL *tl = &taskctl->level[task->level];
tl->tasks[tl->running] = task;
tl->running++;
task->flags = 2; /*活动中*/
return;
} task_remove
void task_remove(struct TASK *task)
{
int i;
struct TASKLEVEL *tl = &taskctl->level[task->level];
/*寻找task所在的位置*/
for (i = 0; i < tl->running; i++) {
if (tl->tasks[i] == task) {
/*在这里 */
break;
}
}
tl->running--;
if (i < tl->now) {
tl->now--; /*需要移动成员,要相应地处理 */
}
if (tl->now >= tl->running) {
/*如果now的值出现异常,则进行修正*/
tl->now = 0;
}
task->flags = 1; /* 休眠中 */
/* 移动 */
for (; i < tl->running; i++) {
tl->tasks[i] = tl->tasks[i + 1];
}
return;
}task_switchsub,用来在任务切换时决定接下来切换到哪个LEVEL
void task_switchsub(void)
{
int i;
/*寻找最上层的LEVEL */
for (i = 0; i < MAX_TASKLEVELS; i++) {
if (taskctl->level[i].running > 0) {
break; /*找到了*/
}
}
taskctl->now_lv = i;
taskctl->lv_change = 0;
return;
}