前两篇文档我一共讲述了3个裸机框架:(1)轮询系统;(2)前后台系统;(3)基于时间片的多任务系统;
今天再谈一谈单链表组成的裸机系统。此写法更加灵活,和时间片的概念类似,
(4)基于单链表的多任务系统
此代码写法分为7步
【1】定义一个表示的任务的结构体类型
timeout表示超时时间,与定时器心跳比较,如果时间到,就执行*pTask指向的函数体
repeat用来周期设置,一般设置成timerout一样,如果设置为0,该任务只是执行一次
*pTask指向该任务要执行的函数体(一般也称为回调函数)
Task_t* next指向链表中的下一个任务节点
//定义一个表示的任务的结构体类型typedef struct Task_t{ unsigned int timeout; // 超时时间(用来与定时器心跳比较) unsigned int repeat;// 循环定时触发时间(周期定时设置),为0时代表单次定时 void (*pTask)(void); //任务的函数指针 struct Task_t* next;// 指向下一个定时器任务节点}Task_t;
【2】定义变量,包含task任务结构体和链表头以及心跳全局变量
//任务结构体变量Task_t task1;Task_t task2;Task_t task3;//表头struct Task_t* g_head_handle=NULL;//心跳计数器unsigned int g_task_ticks=0;
【3】心跳函数将心跳全局变量自加
void Task_Ticks(){ g_task_ticks++;}
【4】任务初始化
void Task_Init(Task_t* hTask, void(*pTask)(), unsigned int timeout, unsigned int repeat){hTask->timeout = g_task_ticks + timeout;hTask->repeat = repeat;hTask->pTask = pTask;}
【5】任务启动和停止函数
//链表中插入任务char Task_Start(Task_t* hTask){struct Task_t* target = g_head_handle;//检查链表中是否已经有该任务while(target) {if(target == hTask) return -1;//already exist.target = target->next;}//链表头部插入任务hTask->next = g_head_handle;g_head_handle = hTask;return 0;}//移除链表中的任务,相当于停止该任务void Task_Stop(Task_t* hTask){struct Task_t** curr;for(curr = &g_head_handle; *curr; ) {struct Task_t* entry = *curr;if (entry == hTask) {*curr = entry->next;} elsecurr = &entry->next;}}
【6】任务循环
//任务循环void Task_Process() { struct Task_t* target;for(target=g_head_handle; target; target=target->next) {if(g_task_ticks >= target->timeout) {if(target->repeat == 0) {Task_Stop(target);} else {target->timeout = g_task_ticks + target->repeat;}target->pTask();
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.