嵌入式工程师实现一个简单的操作系统(六)

本文档详细介绍了嵌入式工程师如何实现一个简单的操作系统,特别是任务调度部分。通过遍历任务数组并根据任务优先级进行选择,确保每个任务都能得到执行。在中断中执行任务调度,实现任务之间的切换。文中还分享了运行结果和遇到的问题,并邀请读者一起探讨和学习。
摘要由CSDN通过智能技术生成

以嵌入式工程师的角度来实现一个简单的操作系统!

1. 前言

继上节课的内容之后,我们距离激动人心的目标还剩下一小步了

现在已经实现了有组织的创建任务,何为有组织,就是创建的任务都有迹可循

现在该思考下一个问题?

2. 继续任务调度

下一个问题是什么呢?

就是现在有N个任务在你面前,现在我们假设他们的任务优先级都是相同的,如何实现让他们轮流执行?

也就是有N个有效任务,每次进入中断选出一个任务去执行,最终实现每个任务都可以的到运行,并且运行的时间或机会是相同的。

截图 2021-10-26 23_49_20

在这个图片中,假设我们就是一共创建了3个任务,那么在全局的任务信息中,刚好是任务0、任务1、任务2三个任务处于有效状态

我们的任务调度规则定义如下:

  1. 遍历任务数组

  2. 查找比当前任务的pid值大的下一个任务

  3. 跳转到该任务执行

  4. 如果发现当前任务的pid已经超过最大pid,返回从0开始循环查找

  5. 如果是只有一个有效任务,该如何设置退出条件呢,不可能一直在进行查找?

按照上面的思路,开始我们的实现流程。

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

运行结果:

image-20211027003528484

好吧!还是除了一些问题,不过看上去问题不大,只要仔细的梳理一下应该可以解决。

代码已经上传到develop_task分支,改天一起debug

欢迎大家持续关注,作为一个小白,我会一步步去实现一些操作系统的基本功能,逐渐丰富

在学习过程中,也会参考一些现成的RTOS或者操作系统的相关实现,比如rtthread等,可以提供一些灵感

在学习中遇到问题欢迎私信一起交流

代码在github同步开源开发,如果无法浏览github代码,可以关注后在后台联系,提供获取方式

附项目链接:GitHub - jhbdream/armv8_os: a simple armv8 operating os for study

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值