FreeRTOS任务状态切换(就绪、挂起、运行、删除、恢复、延时、阻塞)-小结
1. 任务的状态切换
FreeRTOS中任务的状态可分为:未创建态、就绪态、运行态、挂起态、延时态五种状态。
下图总结了一个任务可能出现的任务转换流程:
a: 调用xTaskCreate()函数将新建一个任务,新建的任务会加入到就绪列表,若新建的任务的优先级足够高,调度器会立即将CPU资源分配给他,使它进入运行态。
b: 调度器检查就绪列表中优先级高的任务,并将CPU资源分配给它,使他进入运行态。
c: 运行态的任务可能创建/恢复了新的更高优先级的任务,或者因其操作了某事件(如发送了一个更高优先级的任务需要的消息),使更高优先级的任务进入了就绪表时,再或者更高优先级的任务延时到期自动加入就绪表时,更高优先级的任务将得到CPU资源,使当前运行的任务重新进入就绪态(虽然他还在就绪列表,但由于优先级低,而不被分配CPU资源)。
e: 正在运行的任务(毫无疑问,此时它是就绪表中优先级最高的任务之一),可能想要处理一个事件(如想获取一条消息队列中的消息),此时它将向事件资源管理者(即消息队列)发起申请。如使用以下函数尝试获取队列中的一条消息:
xQueueReceive( QueueHandle_t xQueue,
Void * pvBuffer,
TickType_t xTicksTowait );
d: 任务对申请处理的事件操作成功、或者处理失败但发起获取申请时设置阻塞时间为0,将继续保留CPU资源,继续运行。
f: 任务对申请处理的事件操作失败、并且发起获取申请时设置阻塞时间大于0,则任务会从就绪列表,加入到阻塞延时列表;在等待期间尝试操作事件成功。
n: 运行态的任务调用vTaskDelay(),将把自己从就绪列表搬移到主动延时列表,并让就绪表的其他任务获取CPU资源。
h: 延时态的任务在延时结束时,若优先级比当前任务优先级高,就加入就绪队列,并立即获得CPU资源,进入运行。
g: 延时态的任务在延时结束时,若优先级比当前任务优先级低,就加入就绪队列,但是由于优先级不够,只能等待获取CPU资源。
i: 处于就绪态的任务被正在执行的高优先级的任务挂起,将从就绪列表加入到挂起列表,注意,在挂起列表中的任务,是被打入“冷宫”的任务,除非程序员在写代码时主动调用vTaskResume ()恢复该任务,否则该该任务永远不会回到就绪列表了,更不会被执行。
j: 运行态的任务,主动调用vTaskSuspend()函数挂起自己,将使自己从就绪列表加入挂起列表,并立即执行就绪列表中优先级高的其他任务。
k: 挂起态的任务,不会获得CPU资源了,因此只能等待被正在运行的任务(或中段)唤醒。m: 同上,被唤醒的任务会被从挂起列表加入到就绪列表,若被唤醒的任务的优先级比当前正在运行的任务优先级高,就立即将CPU资源分配给被唤醒的任务。
当然,我们还可以使用vTaskDelete()函数删除一个任务,删除一个任务会将该任务变为未创建态(它什么资源都没有了),除非重新调用vTaskCreat()函数重建它,否则永远不会加入到就绪列表了。
特别地,挂起一个处于延时态的任务会是什么情况,可以再具体讨论。
2.运行态的任务触发切换的情况总结:
正在运行的任务,触发调度器工作的途径有:(但凡有可能引出高优先级任务或中断的操作都会触发调度器检查)
1.创建新任务(显然,新建任务可能比自身的优先级高,因此可能触发调度器)
2.挂起自己、删除自己(往往代表我执行完了)、阻塞延时自己、普通延时自己
3.解阻塞高优先级任务、或触发中断(中断中解阻塞一些高优先级任务)
4.高优先级任务自动就绪(主要指高优先级任务延时结束,定时器任务,定时器任务优先级较高的情况下,若定时溢出,将抢占CPU)
5.恢复一个挂起的高优先级任务。
中断中触发调度器工作的途径有:(但凡有可能使高优先级任务就绪的操作都会触发调度器检查)
1.在中断处理函数中创建新的高优先级任务
2.在中断中释放信号量、消息等使高优先级任务解除阻塞进入就绪。
3.恢复优先级高的任务
(谢谢点赞或收藏)