以嵌入式工程师的角度来实现一个简单的操作系统!
1. 前言
继上节课的内容之后,我们距离激动人心的目标还剩下一小步了
现在已经实现了有组织的创建任务,何为有组织,就是创建的任务都有迹可循
现在该思考下一个问题?
2. 继续任务调度
下一个问题是什么呢?
就是现在有N个任务在你面前,现在我们假设他们的任务优先级都是相同的,如何实现让他们轮流执行?
也就是有N个有效任务,每次进入中断选出一个任务去执行,最终实现每个任务都可以的到运行,并且运行的时间或机会是相同的。
在这个图片中,假设我们就是一共创建了3个任务,那么在全局的任务信息中,刚好是任务0、任务1、任务2三个任务处于有效状态
我们的任务调度规则定义如下:
-
遍历任务数组
-
查找比当前任务的pid值大的下一个任务
-
跳转到该任务执行
-
如果发现当前任务的pid已经超过最大pid,返回从0开始循环查找
-
如果是只有一个有效任务,该如何设置退出条件呢,不可能一直在进行查找?
按照上面的思路,开始我们的实现流程。
3. 编写简单的任务调度函数
3.1 当前任务
我们在任务调度要做的事情就是从A任务切换到B任务
A任务是当前执行的任务
B任务是符合我们任务调度规则,挑选出来的最佳任务
然后调用切换函数进行切换
interrupt_task_switch_from_to(A, B);
既然A和B任务都需要,那我们首先把A任务准备好,但是怎么才能获得A任务呢?
A任务表示当前正在执行的任务,既然我们同一个时刻只能有一个任务在执行,那么我们就定义一个全局变量
g_current_task
,使用该变量记录当前正在执行的任务。既然是要记录这个信息,那么一定会在每次进行任务切换的场景下都应该看到他的身影,当事人必须在场。保证及时准确的记录了当前执行任务的是谁
3.2 目标任务
目标任务的查找也很简单,上面已经讲过了查找原则与方法:
-
从当前任务的位置开始
-
向后遍历全局任务列表
-
循环查找有效任务
-
找到第一个有效任务
-
切换到该任务执行
通过上面的流程,我们可以实现每一个任务都被执行到,OK 现在开始实现。
任务调度算法
struct task *task_schedule_alog() { // 获取下一个任务 struct task *next_task; if(g_current_task == &g_task[G_TASK_NUMBER - 1]) { next_task = &g_task[0]; } else { next_task = g_current_task + 1; } for(int i = 0; i < G_TASK_NUMBER; i++) { if(next_task->pid >= 0) { //找到一个有效任务 返回任务 return next_task; } else if (next_task == &g_task[G_TASK_NUMBER - 1]) { //如果遍历到了末尾,回到头部 next_task = &g_task[0]; } } //目前没有就绪任务,返回空 后续可以考虑添加空闲idel任务 return NULL; }
中断中的任务调度
/** * @brief 定时器中断处理函数,在这里进行任务调度处理 * * @param desc */ void timer_handler(struct irq_desc *desc) { static struct task *from; static struct task *to; arch_timer_compare(arch_timer_frequecy()); from = g_current_task; to = task_schedule_alog(); log_i("switch from pid:[%d]!", from->pid); log_i("switch to pid:[%d]!", to->pid); interrupt_task_switch_from_to(from, to); }
4. 运行结果
创建任务后的测试程序
/** * @brief init create task and switch to taska * */ void my_task_init(void) { global_task_config(); task_create(taska_stack + sizeof(taska_stack), taska_fun); task_create(taskb_stack + sizeof(taskb_stack), taskb_fun); task_switch_to(&taska); }
开跑!!!!!!!!!!!!!!!!!
输入命令: make qemu
运行结果:
好吧!还是除了一些问题,不过看上去问题不大,只要仔细的梳理一下应该可以解决。
代码已经上传到develop_task分支,改天一起debug
欢迎大家持续关注,作为一个小白,我会一步步去实现一些操作系统的基本功能,逐渐丰富
在学习过程中,也会参考一些现成的RTOS或者操作系统的相关实现,比如rtthread等,可以提供一些灵感
在学习中遇到问题欢迎私信一起交流
代码在github同步开源开发,如果无法浏览github代码,可以关注后在后台联系,提供获取方式
附项目链接:GitHub - jhbdream/armv8_os: a simple armv8 operating os for study