“谁来抢 CPU?我来拍板!”——OpenHarmony(LiteOS)内核任务调度全景拆解
本文系统介绍了鸿蒙LiteOS内核的任务调度机制,包括优先级队列、TCB结构、调度算法及同步原语的应用。文章重点阐述了LiteOS基于优先级的抢占式调度策略,高优先级任务的及时响应原理,以及通过Mutex和Semaphore实现任务间同步与资源共享的实践方法。同时提供了可运行的代码示例,展示了中断处理与任务调度的配合方式,并给出优化建议,为开发者掌握鸿蒙系统底层调度机制提供了全面的技术指导。
我是兰瓶Coding,一枚刚踏入鸿蒙领域的转型小白,原是移动开发中级,如下是我学习笔记《零基础学鸿蒙》,若对你所有帮助,还请不吝啬的给个大大的赞~
前言
写底层系统,最怕两个字:卡顿。可一旦你把“任务调度—优先级—中断—同步原语”这条链打通,CPU 用起来会像刀法一样利落:该谁上就谁上,该让就立刻让,既不饿着高优先级,也不累死底层线程。本文按你给的大纲开路:LiteOS 内核 → 调度算法 → 优先级与中断,并把你点名的技术点——Task Control Block(TCB)/ Mutex / Semaphore——统统落到可实战的代码与规则里。咱们开干!💪
一、LiteOS 内核:任务、就绪队列与 TCB 的“底子”
1)任务与就绪模型:优先级队列 + 位图
OpenHarmony 的小型系统常用 LiteOS-A(带 MMU,支持 SMP),LiteOS-M 面向更轻量设备;两者在“高优先级优先 + 同优先级时间片轮转 的抢占式调度”上是一致的:内核维护按优先级划分的就绪队列(每个优先级一条双向链表),并用位图快速定位当前最高可运行优先级;同一优先级的多个任务按时间片轮转。(GitCode)
小贴士:LiteOS 默认优先级通常是 0(最高)~31(最低),可在配置里裁剪调整。(doc.embedfire.com)
2)TCB(Task Control Block):任务的一切都在这
TCB 里记录了任务的上下文、栈指针、优先级、剩余时间片、等待对象(信号量/互斥量)、挂接到各种链表的节点等。你可以把 TCB 看成“内核眼里关于一个任务的全部状态表”。官方文档与源码都明确列举了这些核心字段。(华为云帮助中心)
再抛一个实践向导:LiteOS 的任务创建 API(
LOS_TaskCreate等)会初始化 TCB、挂入就绪队列,并在必要时立即触发调度。(华为云社区)
3)Tick 与 Tickless
时间片与延时都依赖 Tick。内核可配置 LOSCFG_BASE_CORE_TICK_PER_SECOND,并提供 Tick↔毫秒转换、当前 Tick 数等接口;一些资料还提到 tickless 思路:按需唤醒、降低空转中断,提升实时与能效(以 LiteOS-A 资料为例)。(华为云帮助中心)
二、调度算法:高优先级至上,时间片公平轮换
1)核心策略:抢占 + 时间片
- 抢占:一旦出现更高优先级就绪任务,立刻抢占当前任务。
- 轮转:同优先级队列中的多个任务,按时间片轮转(时间片耗尽即从队尾重新排队)。(GitCode)
位图 + 就绪链表的组合让“找最高优先级”是 O(1),调度器非常快。相关源码分析与就绪队列的位图实现可在社区文章里看到。(华为云社区)
2)SMP(多核)要点:亲和、锁与负载
LiteOS-A 支持 SMP:可以设置 CPU 亲和掩码、在多核间调度任务;官方示例就展示了“高优先级任务绑核、低优先级不绑核”的效果以及锁任务调度在 SMP 下的差异(未绑核的任务可在其他 CPU 先跑起来)。(华为云帮助中心)
多核实现涉及到自旋锁、核间中断与负载均衡等机制(工程源码位于 kernel/base/smp 等目录,便于进一步深挖)。(CSDN博客)
3)调度相关“手刹”:TaskLock vs IntLock
LOS_TaskLock/Unlock:锁调度,不关中断;适合保护一小段需要“原子切换/创建”等的代码区间。(GitHub)- 关/开中断(
LOS_IntLock/IntRestore等):屏蔽中断,更重,务必“快进快出”,否则会拖慢中断响应与实时性。(doc.embedfire.com) - 注意:在中断上下文或锁任务期间去做“会睡眠”的操作(如阻塞式延时/等待)会失败或被禁止。(51CTO OST)
三、优先级与中断:谁能打断谁?谁该让谁?
1)中断优先级:比任务更“硬”
中断属于“更紧急”的异步事件,它能打断任何任务。正确姿势是:ISR 里只做轻活(清标志、喂硬件、塞消息/发信号量)、重活交给任务(ISR 末尾唤醒高优先级任务,退出 ISR 后由调度器切换)。官方与教材均强调中断只做最小化处理的设计原则。(doc.embedfire.com)
2)从中断到调度:一次“快进快出”的链路
当 ISR 里释放信号量/事件、或将高优先级任务置就绪,退出中断时调度器会检查是否需要切换到优先级更高的任务——这就是抢占生效的关键时刻。相关“中断接管/统一分发”机制在 LiteOS 社区资料也有详细拆解。(华为云社区)
3)优先级反转与互斥锁
用二值信号量保护资源会有优先级反转风险:低优先级持有资源,高优先级被阻塞,中等优先级抢占导致“高→低”被“卡住”。Mutex 的“优先级继承”可以在持锁期间把低优先级临时抬升,直到释放互斥锁为止,这是 LiteOS 推荐在资源互斥场景使用 Mutex 的根本原因。(doc.embedfire.com)
四、同步原语:Semaphore vs Mutex,怎么选?
1)Semaphore(计数/二值)
- 场景:任务间/中断与任务间同步、“资源数量”控制(计数信号量)。
- API:
LOS_SemCreate/LOS_SemDelete/LOS_SemPend/LOS_SemPost等。 - 中断中使用:通常只允许非阻塞释放(Post),不可在 ISR 里 Pend。(CSDN博客)
2)Mutex(互斥量)
- 场景:独占资源(临界资源)保护;支持所有权、递归,并提供优先级继承以缓解反转。
- API:
LOS_MuxCreate/LOS_MuxDelete/LOS_MuxPend/LOS_MuxPost。 - 对比:同步用 Semaphore,互斥用 Mutex,这是经验定律。(doc.embedfire.com)
五、可跑的最小示例(基于 LiteOS-A 思路,C 伪代码)
目标:演示任务创建 → 基于信号量的 ISR-Task 同步 → 基于互斥量的临界区保护,以及“高优先级任务被唤醒后抢占”。
#include "los_task.h"
#include "los_sem.h"
#include "los_mux.h"
#include "los_typedef.h"
static UINT32 g_sem;
static UINT32 g_mux;
static UINT32 g_tid_high, g_tid_low;
static VOID HighTask(VOID) {
while (1) {
// 等待外设中断释放的信号量(ISR中只做Post)
(VOID)LOS_SemPend(g_sem, LOS_WAIT_FOREVER); // 可被更高优先级抢占
// 进入临界区:互斥保护共享资源
(VOID)LOS_MuxPend(g_mux, LOS_WAIT_FOREVER);
// ... 处理数据(重活) ...
(VOID)LOS_MuxPost(g_mux);
// 业务完成,让出CPU(或下一轮等待)
(VOID)LOS_TaskDelay(1);
}
}
static VOID LowTask(VOID) {
while (1) {
(VOID)LOS_MuxPend(g_mux, LOS_WAIT_FOREVER);
// ... 访问同一资源(短操作),若高优先级阻塞在该锁上,将触发优先级继承 ...
(VOID)LOS_MuxPost(g_mux);
(VOID)LOS_TaskDelay(5);
}
}
// 假想的外设中断服务程序:只做最小动作,释放信号量并尽快返回
VOID MyDevice_ISR(VOID) {
(VOID)LOS_SemPost(g_sem); // 通知高优先级任务去干活
// 退出ISR后,如果HighTask优先级更高,将抢占当前任务
}
UINT32 App_Entry(VOID)
{
TSK_INIT_PARAM_S p = {0};
(VOID)LOS_SemCreate(0, &g_sem);
(VOID)LOS_MuxCreate(&g_mux);
p.pfnTaskEntry = (TSK_ENTRY_FUNC)HighTask;
p.usTaskPrio = 3; // 高优先级(数值越小越高)
p.pcName = "HighTask";
p.uwStackSize = 0x2000;
p.uwResved = LOS_TASK_STATUS_DETACHED;
(VOID)LOS_TaskCreate(&g_tid_high, &p);
p.pfnTaskEntry = (TSK_ENTRY_FUNC)LowTask;
p.usTaskPrio = 8; // 低优先级
p.pcName = "LowTask";
(VOID)LOS_TaskCreate(&g_tid_low, &p);
return LOS_OK;
}
- 要点 1:ISR 里只做 Post,把重活交给任务(提高可维护性与实时性)。(doc.embedfire.com)
- 要点 2:共享资源用 Mutex(可触发优先级继承),而不是二值信号量。(doc.embedfire.com)
- 要点 3:
LOS_TaskCreate完成后,如果有更高优先级就绪任务,会立即触发调度。(华为云社区)
六、定位与优化:调度相关的工程“抓手”
- 时间片/节拍:合理配置
LOSCFG_BASE_CORE_TICK_PER_SECOND;时间片检查在 Tick 中断里进行,时间片耗尽即轮转。(华为云帮助中心) - 锁的粒度:能用
TaskLock就别全局关中断;关中断必须极短。(GitHub) - SMP 绑核/亲和:对实时路径可绑定关键任务到指定 CPU;非关键任务不绑核让负载更均衡。官方 SMP 示例可直接抄作业。(华为云帮助中心)
- 反转预防:临界区统一用 Mutex;对可能长时间占锁的代码做拆分或“生产者-消费者”化解长临界。(doc.embedfire.com)
- 可观测性:把任务状态、就绪队列与时间片剩余等指标打点;LiteOS 提供了一些 demo 与 shell 能力可用于观察任务/队列。(GitHub)
七、知识点回看(你关心的都串上了)
- LiteOS 调度:高优先级优先 + 同优先级时间片轮转的抢占式;就绪队列 + 位图;SMP 支持亲和与多核调度。(GitCode)
- TCB:含栈指针、优先级、时间片、等待对象、链表节点等,任务一切状态都沉淀在 TCB。(华为云帮助中心)
- Semaphore vs Mutex:同步/计数选信号量;资源互斥选互斥量(带优先级继承),防止反转。(doc.embedfire.com)
- 中断与调度:ISR 做轻活,唤醒高优任务;调度在中断退出后生效。关中断要短,锁调度不关中断。(doc.embedfire.com)
- Tick/时间管理:可配节拍率,支持 Tick 转换与统计;资料中亦提到 tickless 思路以降功耗。(华为云帮助中心)
结语:
调度这件事,说难也难——涉及内核每一处时序与边界;说简单也简单——尊重优先级、缩短临界区、ISR 轻、Mutex 护资源。把这几条铁律刻在工程里,你的系统就会规矩而灵动:忙时稳,闲时省。
下一个问题,留给你:你的关键路径里,有没有一个“本可任务化”的 ISR 重活? 😊
参考资料(建议对照源码/官方文档实操)
- **LiteOS-A 调度机制(高优先级优先 + RR)**与小型系统内核文档。(GitCode)
- 任务/就绪/优先级 & TCB 概述(Huawei Cloud 文档)。(华为云帮助中心)
- 任务管理与时间片/节拍配置(Tick 转换、
LOSCFG_BASE_CORE_TICK_PER_SECOND)。(华为云帮助中心) - SMP 任务示例:亲和、锁调度差异。(华为云帮助中心)
- 互斥锁特性(所有权/递归/优先级继承)与使用建议。(doc.embedfire.com)
- ISR 轻量化与中断管理原则。(doc.embedfire.com)
- LiteOS 任务创建/锁调度 Demo(GitHub)。(GitHub)
…
(未完待续)
更多推荐





所有评论(0)