- 打卡等级:初来乍到
- 打卡总天数:1
- 最近打卡:2025-03-10 16:08:45
高级会员
- 积分
- 666
|
发表于 2024-8-14 23:37:56
|
显示全部楼层
随笔--任务状态与任务状态链表
多任务同时执行数量受限于执行单元的数量, 在目前stc8h/32g上只有1个,
Q51定位于stc8h, 因此事实上特定时刻只有一个任务可以被执行, 内核可以看成一个特殊的任务--守护服务任务
中断的处理不在此主题赘述
作为一个任务至少有三种状态, 在执行状态, 未执行状态; 而未执行状态又至少分为2种,
1.就绪:可以执行但暂时没有被执行
2.等待:暂时还不具备执行条件, 需要满足特性条件集合才能具备执行可能性
加上1个在运行任务, 那么所有任务按照状态就有 3个子集合. 3个子集合的元素是不断变化
在一个硬实时操作系统中, 任务的先后排队基于所谓的优先级调度算法有确定的先后顺序
那么, 除了最原始的遍历结构, 顺序表中的双向链表是一个合适的数据结构
Q51中维护一个 QTID(在运行任务ID), 和 fl_wait, fl_ready 2个任务状态双向链表 -- 参考了fanxsp的大作tinyrtos51 也用了类似任务表
不过Q51中只有Fiber才是任务, 而IST是不可切换只能中断的(没有独立栈,在内核上下文执行), 所以最多<10个任务(主要是任务有独立栈)
因此,用4位表示一个ID, 因此链表节点为1个字节, 高4位为prev, 低4位为next
2个任务状态表均为 TASKS + 1字节, 头节点字节如果 为0, 则任务状态内节点为空
任务ID 从 1到10(默认配置为4), 任务ID 0被指代内核任务.
typedef struct _flist
{
u8 fpre: 4; //列表中前一个Fiber的ID,Q51最多支持15个fiber, 因此4位足够
u8 fnext: 4; //列表中后一个Fiber的ID,因为Fiber0是内核不参与排队,因此0代表没有后续
} flist;
因此, 只要从头指针遍历就可以决定, 为加速操作, 加入就绪表采用找到比待加入更低优先级的节点作为next,
因此,任务优先级可以相同. 相同优先级先加入会先选中, 后加入排在同级最后
这样不用类似uc/osii建立影射表. 也可以支持相同优先级任务调度.
供备忘, 参考...
|
|