Lazy loaded image
🪜 实时操作系统
原理篇08-优先级抢占式调度(实践4)
Words 737Read Time 2 min
2026-8-19
2026-8-19
🎯
本篇目标:讲清抢占——高优先级任务就绪的瞬间,怎么把正在跑的低优先级任务“踢下来”。这是 RTOS 实时性的根基。

一、抢占 vs 非抢占

  • 非抢占(合作式):任务自己主动让出(延时、等资源),CPU 才换人。一个任务死循环,全系统陪葬。
  • 抢占式:高优先级任务一就绪,立刻打断当前任务。实时性由调度器保证,不依赖任务“自觉”。
stp_rtos 是抢占式的。抢占的触发点有两个:
  1. tick 中断:延时到期、定时器超时,唤醒更高优先级任务;
  1. API 调用stp_sem_releasestp_thread_resume 等让某个高优先级任务就绪。

二、线程状态机

抢占的前提是任务有清晰的状态。stp_rtos 沿用 RT-Thread 的五态模型:
状态
含义
是否参与调度
初始 INIT
刚创建,还没启动
就绪 READY
在就绪列表排队
运行 RUNNING
正在占用 CPU
当前唯一
挂起 SUSPEND
延时/等资源
关闭 CLOSE
已结束/删除
状态流转:stp_thread_init(初始)→ stp_thread_startup(就绪)→ 调度(运行)→ stp_thread_sleep(挂起)→ 定时器超时(就绪)……
实现细节:stp_rtos 的 stat 不是简单枚举,而是位标志——STP_THREAD_STAT_MASK 取状态位、STP_THREAD_SUSPEND 等标志可叠加。所以判断状态要用 stat & MASK,不能直接 == 比较。

三、抢占是怎么发生的

关键在 stp_schedule 的判断:
它不关心“当前线程是不是自愿的”——只要最高优先级就绪线程不是当前线程,就切。低优先级任务被切走时,现场已由 PendSV 完整保存,等下次轮到它再从断点继续,完全无感。

四、为什么切换必须走 PendSV

抢占可能发生在中断里(比如 tick 中断唤醒了高优先级任务)。如果直接在中断里切上下文,会打断正在执行的 ISR,造成中断延迟不可控。所以:
  1. 中断里只标记需要切换(置 PendSV 挂起位);
  1. 等所有 ISR 跑完,PendSV(最低优先级)最后执行真正的切换。
这就是原理篇09要展开的“确定性”来源之一。

五、小结

  • 抢占 = 调度器发现“最高优先级就绪线程 ≠ 当前线程”就切,不问当前线程意愿;
  • 五态模型让“谁能跑、谁在等”一目了然;
  • 切换动作统一交给最低优先级的 PendSV,保证中断不被切换拖累。
核心一句话:抢占不是“高优先级抢”,而是“调度器永远选最高的那个”。
上一篇
原理篇07-Round-Robin,时间片轮转(实践3)
下一篇
原理篇09-一致性、可预测性、确定性 - 谈中断延迟和线程切换延迟

Comments
Loading...