高优先级任务
需要访问共享资源,但资源被低优先级任务持有。 高优先级任务被迫等待,无法及时执行关键任务。
当高优先级任务被低优先级任务间接阻塞时,系统进入非预期调度状态, 导致实时性被中断破坏。优先级反转是 RTOS 调度系统必须通过 IPC 机制解决的核心问题。
系统运行三个任务:高优先级任务、中优先级任务和低优先级任务。 低优先级任务持有互斥资源时,高优先级任务等待资源,中优先级任务抢占执行, 形成优先级反转场景。通过优先级继承机制解决此问题。
优先级反转的核心概念
优先级反转(Priority Inversion)是指高优先级任务被低优先级任务间接阻塞, 导致系统进入非预期调度状态的现象。这是实时系统中一个经典的调度问题, 会严重影响系统的实时性和可靠性。
需要访问共享资源,但资源被低优先级任务持有。 高优先级任务被迫等待,无法及时执行关键任务。
持有互斥资源(Mutex/Semaphore),正在执行临界区代码。 由于被中优先级任务抢占,无法及时释放资源。
不需要访问共享资源,但优先级高于低优先级任务。 持续抢占 CPU,阻止低优先级任务释放资源。
实际执行顺序变为:中优先级 → 低优先级 → 高优先级, 与预期的优先级顺序完全相反。
优先级反转产生的必要条件
优先级反转的发生需要同时满足三个条件:资源占用、高优先级阻塞和中优先级抢占。 只有这三个条件同时存在时,才会形成典型的优先级反转场景。
优先级反转对实时系统的危害
避免和修复优先级反转的方法
为了解决优先级反转问题,RTOS 提供了多种机制。 其中最常用的是优先级继承和优先级天花板两种策略。
机制原理:低优先级任务临时继承高优先级任务优先级
触发时机:高优先级任务等待资源时
执行效果:低优先级任务以高优先级执行,快速释放资源
恢复时机:资源释放后恢复原优先级
HRTOS 实现:通过 os_mutex_lock 自动触发优先级继承
机制原理:资源绑定最高优先级限制,避免中断抢占
触发时机:任务获取资源时
执行效果:任务立即提升到资源的天花板优先级
恢复时机:释放资源后恢复原优先级
优势特点:避免死锁,但可能降低系统灵活性
优先级反转涉及的关键 API
功能:进入临界区保护
作用:禁用中断,保护共享资源访问
使用场景:访问就绪队列等关键数据结构
配对调用:必须与 os_exit_critical 配对使用
功能:运行调度器
作用:执行任务调度决策
调用时机:调度请求触发时
决策依据:就绪队列和任务优先级
功能:主动让出 CPU
作用:任务主动触发调度
使用场景:任务完成当前工作后
调度效果:任务从 Running 状态进入 Ready 状态
功能:释放互斥锁
作用:释放资源并恢复任务优先级
优先级恢复:继承的优先级在解锁时恢复
唤醒等待:唤醒等待该资源的高优先级任务
优先级反转场景的示例实现
high_task、mid_task 和 low_task 任务函数,展示优先级反转场景。 高优先级任务(优先级5)需要访问互斥资源,低优先级任务(优先级1)持有资源, 中优先级任务(优先级3)抢占执行,形成优先级反转。
#include "hrtos.h"
sbit LED_HIGH = P1^0;
sbit LED_MID = P1^1;
sbit LED_LOW = P1^2;
static void high_task(void)
{
while(1)
{
os_mutex_lock(0);
LED_HIGH = ~LED_HIGH;
os_mutex_unlock(0);
os_delay(10);
}
}
static void mid_task(void)
{
while(1)
{
LED_MID = ~LED_MID;
volatile u16 i;
for(i = 0; i < 2000; i++);
os_delay(20);
}
}
static void low_task(void)
{
while(1)
{
os_mutex_lock(0);
LED_LOW = ~LED_LOW;
os_delay(50);
os_mutex_unlock(0);
}
}
hrtos_main 函数,初始化互斥锁并创建三个任务
void hrtos_main(void)
{
os_mutex_init(0);
os_task_create((unsigned int)high_task, 1, 5, 5);
os_task_create((unsigned int)mid_task, 2, 3, 5);
os_task_create((unsigned int)low_task, 3, 1, 5);
}
深入学习的相关资源