接着上一讲
奔腾的心:FreeRTOS 从入门到精通5--详解任务管理上zhuanlan.zhihu.com在这一讲中我将要介绍任务的运行模式,同时与可编程控制器(PLC)以及安卓系统的运行模式进行比较。我在德国读书时专业是嵌入式开发,工作后从事的是西门子PCS7过程系统的编程,业余学习了安卓开发。在学习的过程中,我逐渐意识到单片机,PLC和智能手机本质上上都是一类控制器,很多对于系统开发的理念都是相近互通的,基于此便产生一种想法,想在介绍FreeRTOS的任务管理时,同时对比下PLC和安卓的任务管理机制。
首先,我们先看一下FreeRTOS的任务状态的转化图
其中每个状态的含义如下
- 阻塞状态(Blocked)当任务等待某个事件或信号的时候处于此状态
- 挂起状态(Suspended)当任务被vTaskSuspend()函数禁止运行的时候处于此状态
- 就绪状态(Ready)当任务没有被阻塞或者挂起等待运行的时候处于此状态
- 运行状态(Running)当任务被内核调度执行的时候处于此状态
在系统初始化所有任务被创建的时候,任务一开始都处于就绪状态(Ready),然后内核调度器开始调度首先选择执行优先级最高的任务,此时被执行的任务处于运行状态(Running)。当任务执行延时命令或者等待某个同步事件的时候便交出了自己的运行权,此时将处于阻塞状态(Blocked)。在任务运行的时候,它可以通过vTaskSuspend()函数将其他任务或者自身挂起进入挂起状态(Suspended)。被挂起的任务只有通过vTaskResume()函数恢复成就绪状态(Ready)。
接下来,让我们看看程序在可编程逻辑器(PLC)中的运行机制。
在PLC中,一般任务都是写好后顺序执行的。在读取输入阶段,PLC扫描所有输入端子,并将各输入端的通/断状态存入相对应的输入映像寄存器中,刷新输入映像寄存器的值。CPU对用户程序按顺序进行扫描,逐条执行程序指令。在用户程序执行完毕后,PLC将输出映像寄存器中的通/断状态送到输出锁存器中,通过输出端子驱动用户输出设备或带动负载。在这里可以把PLC中运行的任务看作是优先级相同的任务,任务之间不会互相抢占运行的权利,内核调度器类似合作式调度(Co-operative Scheduling)- 按照预设的顺序先后执行控制任务。因为PLC程序的运行都是可预测的,所以PLC更适合对稳定性实时性要求更高的工业领域。
最后,让我们看看安卓系统中任务的运行模式,有个专有名词叫生命周期。在安卓编程中,每个活动(Activity)包含一个画面和对应的程序,这里可以类比成一个任务。活动通过OnCreate()函数创建,通过OnStart()函数启动,当被其他活动抢占之后会通过onPause()函数暂停并通过onStop()函数停止(此时活动将在手机屏幕上消失)。被停止的活动通过OnRestart()函数重新运行,或者通过onDestroy()函数被销毁。
FreeRTOS中任务的运行状态机制和安卓编程中活动的生命周期比较相似。FreeRTOS通过xTaskCreate()函数创建任务,相当于安卓的onCreate()函数;FreeRTOS通过vTaskSuspend()函数挂起任务,相当于安卓的onPause()函数;FreeRTOS通过vTaskResume()函数恢复任务到就绪状态,相当于安卓的onResume()函数;FreeRTOS通过vTaskDelete()函数删除任务,相当于安卓的onDestroy()函数。通过这些相似之处可以看到,学好FreeRTOS对于安卓开发也有裨益,而玩转了嵌入式和安卓编程,融会贯通硬件和软件开发,你将立于紫禁城之巅,成为每个产品经理最缺的那个程序员大神。
FreeRTOS的调度算法及配置
抢占式时间片调度(Prioritized Pre-emptive Scheduling with Time Slicing)
这是比较通用的调度方式,上一篇提到的温度检测系统采用的就是这种方式。内核调度器在每个时间片结束的时候执行一次,选择处于就绪状态的任务中优先级最高的任务置于下一个时间片执行。如果优先级相同的话则交替执行。此时,FreeRTOSConfig.h头文件的设置如下:
configUSE_PREEMPTION(允许抢占) 1
configUSE_TIME_SLICING(采用时间片) 1
抢占式无时间片调度(Prioritized Pre-emptive Scheduling without Time Slicing)
在这种调度方式下,因为没有采取时间片,所以调度器的执行开销会比较小。如果两个任务的优先级相同的话,在抢占式时间片调度下,两个任务会交替运行;然而在抢占式无时间片调度下,当前运行的任务会一直运行,直到它进入阻塞或者挂起状态,另一个相同优先级的任务才会运行。高优先级的任务会抢占低优先任务。此时,FreeRTOSConfig.h头文件的设置如下:
configUSE_PREEMPTION(允许抢占) 1
configUSE_TIME_SLICING(采用时间片) 0
合作式调度(Co-operative Scheduling)
这种调度模式下,当前执行任务将会一直运行,同时高优先级的任务不会抢占低优先级任务。内核调度只会在当前执行任务进入阻塞状态的时候才会执行,选择处于就绪状态的任务中优先级最高的任务进行执行。此时,FreeRTOSConfig.h头文件的设置如下:
configUSE_PREEMPTION(允许抢占) 0
configUSE_TIME_SLICING(采用时间片) 任意
在下一讲中,我将介绍FreeRTOS中队列管理的知识。队列管理(Queue Management)提供了任务之间,任务和中断之间的通讯机制。
奔腾的心:FreeRTOS 从入门到精通7--队列管理zhuanlan.zhihu.com