"); //-->
在嵌入式系统中,如果使用基于优先级调度算法的RTOS,系统中可能发生优先级反转现象。优先级反转用来描述系统中高优先级任务由于等待低优先级任务完成才能继续执行的情景,通常发生在试图获取信号量使用权或共享资源时。优先级反转可能会导致严重的后果。在小型嵌入式系统设计中,我们需要考虑如何访问共享资源,避免资源竞争,防止优先级反转发生。
本文将介绍如何通过分析工具检测OPENRTOS(FreeRTOS)应用中的优先级反转现象,如何最小化优先级反转的影响,及如何在设计中避免优先级反转问题。
使用Tracealyzer工具检测优先级反转现象
Tracealyzer是一个可视化分析工具,以图形化的方式展示事件发生的序列。我们通过一个Percepio公司的示例说明如何使用Tracealyzer检测优先级反转问题。应用中存在一个随机复位问题,在复位异常处理中设置断点,发现该问题是由于看门狗定时器超时引起的,看门狗定时器应该在一个周期运行的高优先任务中重置。
插入自定义Tracealyzer用户事件帮助工程师获得更大的能见度。“用户事件”类似于经典的“printf()”调用。在此示例中,在看门狗计时器被重置或超时位置添加用户事件。用户事件还支持数据参数,记录重置之前的计时器值,以查看看门狗“margin”,即剩下的时间。捕获结果如图1所示。
图1 用户事件示例
从图中我们可以看到SamplerTask任务正常运行,但任务在最后一个执行过程中没有清除看门狗计时器,导致看门狗重置事件发生。SamplerTask为什么没有复位看门狗定时器?在Tracealyzer中使能Kernel Service calls,查看任务当前在执行什么操作,捕获结果如图2所示。
图2 系统服务调用示例
SamplerTask任务的最后一个动作是调用OPENRTOS函数xQueueSend,将消息放入消息队列中。注意,该标签显示为红色,表示xQueueSend 函数将阻塞任务,任务阻塞导致看门狗定时器复位之前,任务切换至ServerTask,从而导致看门狗超时,引起系统复位。
为什么xQueueSend阻塞了任务?双击此事件标签,打开Object History视图,显示xQueueSend函数操作队列“ControlQueue”的所有操作,如图3所示。图中最右边一列展示了队列存储的消息。可以看到消息队列已经包含五个消息,队列已满,因此xQueueSend操作引起任务阻塞。但ControlTask任务应该读取队列数据并清空队列缓冲区,为什么预期的行为没有发生?
图3 Object history视图
研究该问题,分析看门狗的margin如何随时间而变化。这些信息记录在User Event Logging中,使用User Event Signal Plot,我们可以绘制看门狗margin随时间的变化。在同一时间轴上添加CPU负载图,我们可以看到任务执行如何影响看门狗margin,如图4所示。
图4 User event Single slot视图
在CPU负载图中,我们可以看到跟踪的后半部分,ServerTask执行消耗了约一半的跟踪时间,这似乎影响了看门狗的margin。ServerTask任务(亮绿色)比ControlTask任务(深绿色)优先级高,所以当ServerTask任务消耗更多CPU时间后,ControlTask任务得到的CPU减少。由于高优先级的ServerTask任务占用了许多CPU时间,导致ControlTask无法及时读取消息队列中的数据。这是优先反转问题的一个例子,SamplerTask任务被不相关的低优先级任务阻塞。
解决方案
更改任务优先级
一种解决办法是改变优先级,使ControlTask任务的优先级高于ServerTask。图5显示了交换两个任务调度优先级后的运行结果。系统行为更稳定。SamplerTask任务(红色)的CPU负载稳定在20%左右,其周期行为稳定,看门狗margin为一条“线”,维持在10毫秒。看门狗不会超时-问题解决了!(注意:任务由于优先级改变,对应的显示颜色也发生了变化)。
图5 交换ServerTask与ControlTask优先级结果
使用互斥信号量
当多个任务访问同一资源时,例如网络驱动或图形显示,可能会发生优先级反转。这种情况下,可以使用互斥信号量降低优先级反转的影响。
互斥信号量是包含优先级继承机制的二值信号量,二值信号量更适合实现任务间或任务与中断服务之间的同步操作,互斥信号量更适用于互斥实现。
用作互斥机制时,互斥信号量相当于一个令牌,保护共享资源。当任务希望访问该共享资源时,需要首先获得(“take”)令牌。资源使用完后,任务必须释放令牌,让其它任务可以访问相同的资源。
互斥信号量允许指定阻塞时间,阻塞时间指示一个任务在尝试获取令牌时,如果令牌不可用,任务可以阻塞的最大节拍数。然而,与二值信号量的区别在于,互斥量支持优先级继承机制。这意味着,如果有一个高优先级的任务在试图获取当前持有令牌的低优先级任务占用的资源时,系统会临时提升占有资源的任务优先级别为被阻塞任务的优先级。该机制确保高优先级的阻塞时间尽量短,从而尽量减少优先级反转的时间。
优先级继承并不能解决优先级反转问题,它只是最小化了反转在某些情况下产生的影响。硬实时应用设计时,需保证优先级反转不会发生。
使用Gatekeeper任务
在访问系统资源时,为了避免优先级反转问题,我们推荐使用“Gatekeeper”任务。Gatekeeper任务结构如图6所示,包含一个控制资源的任务,接收数据/命令的队列和一个回调函数。
应用任务不直接访问资源,而是将数据/命令写入队列。Gatekeeper任务处理接收到的数据/命令,并相应地更新资源。资源状态发生改变时,将触发ISR (例如接收到一个新的网络消息),将信息放置在队列中,然后,Gatekeeper任务将执行回调函数,将新的数据传给应用任务。
此方法防止了系统资源访问时优先级反转的出现,是我们推荐的解决办法。
图6 Gatekeeper任务
结论
使用实时内核,优先级反转问题是实时系统中出现得非常多的问题。在嵌入式系统系统设计时,应尽量避免优先级反转发生,或者可以通过可视化分析工具捕获该问题,通过相应的RTOS方法降低其风险。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。
eleaction01 阅读:2955