FreeRtos内核源码分析(九)——协程

目录

一、协程简介

二、协程工作机制

2.1 协程控制块结构

2.2 协程管理方式

2.3 协程调度方式

2.4 协程通信机制

三、协程状态及状态切换

3.1 协程状态

3.2 状态切换

四、协程创建

五、协程调度分析

5.1 源码分析

5.2 逻辑图分析

六、协程通信

6.1 协程发送消息(线程)

6.2 协程接收消息(线程)

6.3 向协程发送消息(中断) 

6.4 接收协程消息(中断)


本章基于FreeRtos V9.0.0版本分析

一、协程简介

        FreeRtos中应用既可以使用任务,也可以使用协程(Co-Routine),或者两者混合使用。但是任务和协程使用不同的API函数,因此不能通过队列(信号量)将数据从任务发给协程,反之亦然。

       与任务相比,协程的调度在线程中,不支持抢占调度,只能使用协作式调度,实时精度低;由于没有中断参与,协程具有占用资源少、CPU利用率高的优点。协程与定时器有点类似。

注意:任务与协程混合使用时,协程的调度可以在某个任务中。

二、协程工作机制

2.1 协程控制块结构

        与任务相比较,协程控制块即可表示整个协程,不存在协程栈,也不存在上下文切换。

// 协程的回调函数(参数1:协程控制块句柄,参数2:协程ID uxIndex)
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );

// 协程结构体
typedef struct corCoRoutineControlBlock
{
	crCOROUTINE_CODE 	pxCoRoutineFunction;    /*< 入口函数. */
	ListItem_t			xGenericListItem;	    /*< 协程状态条目,用于状态切换. */
	ListItem_t			xEventListItem;		    /*< 协程事项表项,用于信号等阻塞*/
	UBaseType_t 		uxPriority;			    /*< 优先级. */
	UBaseType_t 		uxIndex;			    /*< ID,当多个协程使用相同入口函数时,用于区分协同例程,为回调函数的第二个参数 */
	uint16_t 			uxState;			    /*< 协程状态. */
} CRCB_t; /* 协同程序控制块。Note的大小必须与TCB_t的uxPriority相同. */

2.2 协程管理方式

        协程的管理方式与任务管理类似,通过链表管理,链表定义如下:

/* 就绪和闭锁协程队列. --------------------*/
static List_t pxReadyCoRoutineLists[configMAX_CO_ROUTINE_PRIORITIES];	/*< 就绪链表. */
static List_t xDelayedCoRoutineList1;	/*< 阻塞链表1. */
static List_t xDelayedCoRoutineList2;	/*< 阻塞链表2. */
static List_t * pxDelayedCoRoutineList;	/*< 指向当前阻塞链表 */
static List_t * pxOverflowDelayedCoRoutineList;	/*< 指向溢出阻塞链表. */
static List_t xPendingReadyCoRoutineList;	    /*<  临时就绪链表,*/

        链表结构和操作方式可参考《基于STM32F103ZE平台分析FreeRtos(二)——任务部分》章节。

就绪链表:链接就绪协程,根据协程插入链表的先后顺序排列,新就绪协程插入到链表尾部。

阻塞链表:连接阻塞协程,采用双链表管理,阻塞协程根据阻塞时间片大小,按照从大到小的顺序插入链表,表头指向阻塞时间最近的协程。

双链表管理方式可参考《基于STM32F103ZE平台分析FreeRtos(二)——任务部分》章节。

临时就绪链表:中断中使用,当中断需要释放阻塞协程时,为避免数据冲突,不会直接操作就绪链表,会将释放的协程先插入到临时就绪链表。在协程调度中,由调度器将临时链表中的协程移到正式就绪链表中。

2.3 协程调度方式

        协程只有协作式调度,调度器在线程中循环进行,不存在上下文切换,一个协程执行完成后才能执行下一个协程,每次从协程的回调函数入口执行,每次循环执行一个协程的回调函数。

        调度的原则是选择优先级最高的协程执行,如果优先级最高的协程有多个,则轮询执行这几个协程。

2.4 协程通信机制

        协程支持从中断和线程中以FIFO方式操作消息队列,实现协程间的通信,操作过程与任务类似,但是不能与任务共用消息队列。

        当协程与任务混合使用时,协程调度基于某个任务存在,此时协程可以通过调用任务的通信接口与任务通信,其本质还是任务间的通信。

三、协程状态及状态切换

3.1 协程状态

1、绪( Ready:该协程在就绪链表(pxReadyCoRoutineLists[])或临时就绪链表(xPendingReadyCoRoutineList)中, 就绪的协程已经具备执行的能力,等待调度器调度。

2、行(Running:该协程在就绪列表中,但是正在调度中执行, 调度器选择运行的永远是处于最高优先级的就绪态协程。
3、塞(Blocked: 如果协程正在等待消息,就会从就绪链表移除,并根据阻塞时间插入到阻塞链表中。

3.2 状态切换

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿来不是梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值