大家在进行RTOS开发的过程中一定有了解过优先级翻转这个问题,就是低优先级任务会由于共享资源优先高优先任务先执行,这违背了抢占式内核的实时表现,解决RTOS中优先级翻转问题的核心在于管理共享资源访问,特别是互斥锁的使用策略,目前主流的RTOS都有集成优先级反转策略的优化措施,不够每家各有不同,不过解决该问题的方案主要有如下几种:
一、根本原因
优先级翻转指:
- 低优先级任务(L) 持有互斥锁(Mutex)访问共享资源。
- 中优先级任务(M) 抢占L,但不需要该资源。
- 高优先级任务(H) 启动并等待该锁,被阻塞。
- M 持续运行,导致 H 被迫等待 M 和 L,违反实时性。
二、多种主流解决方案
1. 优先级继承协议
它的实现原理就是:当高优先级任务(H)因锁被低优先级任务(L)持有而阻塞时,临时提升 L 的优先级至与 H 相同。
所以低优先任务快速执行完毕释放锁,以阻止中优先级任务(M)抢占 L。多数现代 RTOS(如 FreeRTOS、µC/OS)内置支持。像FreeRTOS创建支持优先级继承的 Mutex,请求锁时自动触发优先级继承。
2. 优先级天花板协议
这种方案可以为每个互斥锁预设一个优先级上限(Ceiling Priority),任务持有该锁时,优先级自动提升至上限值。 上限优先级需高于所有可能请求该锁的任务的优先级。避免优先级继承的动态调整。
所以这种解决方案可以完全防止翻转,并且没有无死锁风险。 像VxWorks的pthread_mutexattr_setprioceiling()
3. 时间限制协议
对任务设置阻塞时间上限(xBlockTime
),超时则放弃请求或执行错误处理,其核心就是为资源请求设置阻塞时间上限,当高优先级任务等待锁的时间超过预设阈值,系统强制触发超时处理机制,避免无限期阻塞。
// FreeRTOS 示例(单位:Tick)
const TickType_t timeout_ticks = pdMS_TO_TICKS(5); // 5ms超时
if (xSemaphoreTake(mutex, timeout_ticks) == pdPASS) {
// 成功获取锁 → 访问共享资源
xSemaphoreGive(mutex);
} else {
// 超时处理分支
_handle_lock_timeout();
}
- 适用场景:对响应时间有严格约束的系统(如汽车ECU)。
虽然RTOS提供了一下了一些API接口和策略对此类问题进行优化,其实在我们的设计早期就可以在一定程度上进行此类问题的规避,最重要的就是避免高优先级任务依赖低优先级资源,通过设计规避锁依赖链。 当然你月可以最小化临界区,以缩短锁持有时间;还有既然是锁引入的就采用无锁数据结构替代锁,从而规避该问题。
END
作者:Mr.Deng
来源:嵌入式专栏
推荐阅读
欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。