cot_os 是一个轻量级的协程调度系统,使用了标准库头文件 <setjmp.h>
中的 setjmp
和 longjmp
两个函数,构建了一个简单的查询式协作多任务系统,支持独立栈和共享栈两种任务。
- 其中涉及到获取和设置栈的地址操作,因此还需要根据不同平台提供获取和设置栈顶的地址操作(一般是汇编语言,因为涉及到寄存器)
- 该调度系统仅运行在一个实际的线程中,因此本质上属于协程
- 独立栈任务都有自己独立的运行栈空间,互不干扰;共享栈任务共用一个运行栈空间。
无任务优先级抢占的功能。
任务切换的时机完全取决于正在运行的任务,体现协作。
支持独立栈和共享栈两种任务,根据不同的应用场景决定。
查询式的调度方式,当前任务切换时,查询下个任务是否需要执行。
移植性强,只需要修改设置栈和获取当前栈地址的宏即可。
相对于时间片论法的任务调度来说,查询式协作多任务系统有以下特点:
- 无需使用定时器做为任务调度
- 每个任务都可以使用
while
循环,用于执行任务并保持程序的运行,程序结构清晰- 每个任务都可以随时阻塞等待,甚至可以在嵌套的子函数中阻塞等待
- 通过阻塞等待,无需使用状态机等较为复杂的方式来优化缩减每个任务的执行时长
相对于RTOS操作系统来说,查询式协作多任务系统有以下特点:
- 没有任务优先级抢占式的功能,因此临界资源(中断除外)和优先级反转的问题也不存在
- 允许用户或应用程序根据需要自由地切换到下一个就绪任务
- 通过自主调度和管理任务,查询式协作多任务系统可以提高工作效率
- 没有操作系统的复杂
运行栈空间:程序运行中发生函数调用等情况需要使用的栈内存空间
每个独立栈任务都拥有自己独立的运行栈空间,可以随时随地阻塞等待,保存上下文后切换到下一个任务执行
独立栈任务在切换下一个任务时,不会操作运行栈,只对上下文切换
每个共享栈任务都没有自己独立的运行栈空间,虽然也能阻塞等待,但是仅限于在任务入口函数中使用,禁止在任务的子函数(嵌套函数)中阻塞等待;并且在该任务入口函数中不建议定义相关变量。
- 每个任务有自己的独立备份栈(用来备份运行栈的栈顶部分数据);运行栈通常比备份栈要大很多,否则任务函数无法正常运行多级嵌套的函数
- 共享栈任务在切换下一个任务时会将当前运行栈(共享栈)的数据拷贝到内存备份起来,等下次即将执行时再从内存中拷贝到运行栈(共享栈)进行恢复
- 该类型任务适合于轻量的任务处理,一般都是调用封装好的函数即可
注:这里的共享栈任务和常规的实现有一些差异,常规的实现是使用堆申请内存保存栈的数据,用多少申请多少进行保存,而这里的实现仅仅保存了一部分数据。
- 独立栈任务中可以创建新的独立栈任务和共享栈任务
- 共享栈任务中同样可以创建新的独立栈任务和共享栈任务,而且在创建共享栈任务时可以使用同一个共享栈
当前任务阻塞提供两种方式:
可以使用事件阻塞的方式进行任务间的同步
对于创建独立栈任务还是共享栈任务的示例代码:
uint8_t g_task1Stack[1024 * 2];
uint8_t g_task2Stack[1024 * 2];
uint8_t g_task3Stack[1024 * 2];
uint8_t g_sharedStack[1024 * 2];
// 执行完成就退出的任务
void taskfunc3(int arg)
{
...
cotOs_Wait(1000);
...
cotOs_Wait(1000);
}
void taskfunc1(int arg)
{
/* 不管taskfunc1是独立栈任务还是共享栈任务,都支持创建子任务 */
cotOs_CreatTask(taskfunc3, COT_OS_UNIQUE_STACK, g_task3Stack, sizeof(g_task3Stack), 0); // 创建独立栈任务
cotOs_CreatTask(taskfunc3, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0); // 创建共享栈任务
while (1)
{
...
cotOs_Wait(1000);
}
}
void taskfunc2(int arg)
{
while (1)
{
...
cotOs_Wait(10);
}
}
int main(void)
{
cotOs_Init(GetTimerMs);
#if 0
/* 创建独立栈任务 */
cotOs_CreatTask(taskfunc1, COT_OS_UNIQUE_STACK, g_task1Stack, sizeof(g_task1Stack), 0);
cotOs_CreatTask(taskfunc2, COT_OS_UNIQUE_STACK, g_task2Stack, sizeof(g_task2Stack), 0);
#else
/* 创建共享栈任务 */
cotOs_CreatTask(taskfunc1, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0);
cotOs_CreatTask(taskfunc2, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0);
#endif
cotOs_Start();
}
对于创建独立栈任务还是共享栈任务,共享栈任务有限制要求,禁止在任务入口函数的嵌套函数中阻塞
uint8_t g_task1Stack[1024 * 2];
uint8_t g_sharedStack[1024 * 2];
void func1_1(void)
{
...
cotOs_Wait(1000);
...
cotOs_Wait(1000);
}
/* 独立栈任务 */
void taskfunc1(int arg)
{
int arr[10]; // 可以直接定义变量使用
while (1)
{
func1_1(); // 可以在嵌套函数中使用阻塞等待
...
cotOs_Wait(1000);
}
}
void func2_1(void)
{
...
}
/* 共享栈任务 */
void taskfunc2(int arg)
{
int arr[10]; // 共享栈任务的入口函数依然可以定义变量使用,不会丢失数据
while (1)
{
func2_1(); // 禁止在嵌套函数中使用阻塞等待
...
cotOs_Wait(10);
}
}
int main(void)
{
cotOs_Init(GetTimerMs);
/* 创建独立栈任务 */
cotOs_CreatTask(taskfunc1, COT_OS_UNIQUE_STACK, g_task1Stack, sizeof(g_task1Stack), 0);
/* 创建共享栈任务 */
cotOs_CreatTask(taskfunc2, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0);
cotOs_Start();
}
通过时间和事件的方式阻塞
uint8_t g_task1Stack[1024 * 2];
uint8_t g_task2Stack[1024 * 2];
uint8_t g_task3Stack[1024 * 2];
uint8_t g_sharedStack[1024 * 2];
CotOSCondition_t g_eventCv;
// 执行完成就退出的任务
void taskfunc3(int arg)
{
...
cotOs_ConditionWait(&g_eventCv);
...
}
void taskfunc1(int arg)
{
cotOsTask_t task = cotOs_CreatTask(taskfunc3, COT_OS_UNIQUE_STACK, g_task3Stack, sizeof(g_task3Stack), 0);
while (1)
{
...
cotOs_Wait(1000);
if (...)
{
// 等待 taskfunc3 任务运行结束后才退出 taskfunc1
cotOs_Join(task);
break;
}
}
}
void taskfunc2(int arg)
{
while (1)
{
...
cotOs_Wait(10);
if (...)
{
cotOs_ConditionNotify(&g_eventCv); // 通知 taskfunc3 继续执行
}
}
}
int main(void)
{
cotOs_Init(GetTimerMs);
cotOs_CreatTask(taskfunc1, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0);
cotOs_CreatTask(taskfunc2, COT_OS_SHARED_STACK, g_sharedStack, sizeof(g_sharedStack), 0);
cotOs_Start();
}
独立栈任务(有栈任务)
共享栈任务(无栈任务)
demo代码链接:stm32 菜单效果demo
const_zpc@163.com
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。