作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习
擅长领域:驱动开发,嵌入式软件开发,BSP开发
作者主页:一个平凡而乐于分享的小比特的个人主页
文章收录专栏:UCOS-III,本专栏为UCOS-III学习记录
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
中断抢占和任务抢占的区别
任务抢占 (Task Preemption)
定义:
- 任务之间的抢占
- 发生在任务调度层面
- 由RTOS调度器管理
触发条件:
// 例子:任务A正在运行,此时...
任务B从阻塞态变为就绪态,且 优先级(B) > 优先级(A)
- 更高优先级任务变为就绪态
- 当前任务降低了自身优先级
- 其他任务提高了优先级
发生时机:
- 在调度点发生 :
- 任务调用
OSTimeDly() - 任务调用
OSSemPend()(信号量不可用时) - 任务调用
OSFlagPend()等 - 任务主动调用
OSTaskSuspend()
- 任务调用
中断抢占 (Interrupt Preemption)
定义:
- 中断对任务的抢占
- 发生在硬件中断层面
- 由CPU硬件管理
触发条件:
// 任何硬件中断发生:
SysTick中断、定时器中断、串口中断、GPIO中断等
发生时机:
- 任何时刻,即使任务正在运行关键代码
- 与任务状态无关(运行态、就绪态都会被中断)
关键区别对比
| 特性 | 任务抢占 | 中断抢占 |
|---|---|---|
| 触发源 | 任务状态变化 | 硬件中断 |
| 管理者 | RTOS调度器 | CPU硬件 |
| 发生时机 | 只在调度点 | 任何时刻 |
| 可预测性 | 相对可预测 | 完全异步 |
| 优先级依据 | 任务优先级 | 中断优先级 |
| 对任务状态要求 | 只能抢占运行态任务 | 可中断任何状态的任务 |
eg:
任务抢占的例子:
c
void middle_task(void *p_arg)
{
while(1)
{
printf("middle_task正在运行!!!\r\n");
OSTimeDly(1000, OS_OPT_TIME_DLY, &err); // ← 调度点!
// 在这里可能发生任务抢占
}
}
当 middle_task 调用 OSTimeDly() 时,调度器选择就绪队列中最高优先级的任务运行。
中断抢占的例子:
c
void low_task(void *p_arg)
{
while(1)
{
printf("low_task正在运行!!\r\n");
delay_ms(3000); // ← 任何时刻都可能被中断抢占!
// 即使在delay_ms循环中,也会被SysTick中断
}
}
实际运行中的交互
中断抢占 → 任务抢占的连锁反应:
low_task 运行 delay_ms(3000)
↓
SysTick中断发生(中断抢占)
↓
在ISR中检查到 middle_task 的 OSTimeDly 到期
↓
ISR标记 middle_task 为就绪态
↓
中断返回前,调度器进行任务调度
↓
由于 middle_task 优先级 > low_task 优先级
↓
发生任务抢占,切换到 middle_task
简单来说:
- 中断抢占:硬件中断"打断"当前任务(无论它在做什么)
- 任务抢占:调度器在合适时机"换人"(只在调度点发生)
在你的优先级翻转场景中:
- 首先 发生中断抢占(SysTick中断)
- 然后 在中断服务程序中触发任务抢占(调度器选择更高优先级任务)
- 两者配合才使得
middle_task能在low_task的delay_ms(3000)期间运行