LiteOS-M移植-两种工程范式-直接改内核VS完整保留内核
LiteOS-M 移植:两种工程范式——直接修改内核源码 VS 完整保留内核源码
技术博客|面向刚接触 RTOS 移植的初学者
一句话结论:两种方式都能跑通工程,但维护成本、后续内核升级代价完全不同。 再强调一遍:磁盘源码 ≠ 烧录固件,磁盘上的冗余源码不会增大芯片固件镜像。
前言
很多同学做 LiteOS-M(鸿蒙轻量内核) 移植时,会遇到两条完全不同的实践路线:
- 路线 1:直接进入内核仓库,修改内核内部的
.c / .h,改完编译跑通。我早期的移植博客就是这种验证方式,确实可以跑起来。 - 路线 2:完整原样保留
kernel_liteos_m这个 Git 仓库,不改动内核内部任何文件;所有板级修改、适配,全部放到工程外部的 BSP / board 目录(如targets),通过编译列表与配置宏做裁剪适配。
疑问就来了:两种都能跑,到底选哪一种?直接改内核源码会有什么隐患?把全套内核源码完整放在磁盘上,会不会把没用到的组件也编译进固件?
很多初学者容易混淆两个概念:「开发主机磁盘上的源码文件」 和 「最终编译、烧录进芯片的固件镜像」。本文结合实战经验,把两种范式讲清楚——不绑定任何具体工程,只讲通用原理和选型思路。
读完这篇文章,你会搞清楚:
- 直接改内核源码,为什么「能跑」却「不适合量产」;
- 完整保留内核源码的工程,到底靠什么做裁剪;
- 为什么磁盘上的冗余源码不会撑大固件;
- 商业产品有哪三条可行路线,各自怎么选;
- 这两种范式到底怎么选,落到自己的项目里该注意什么。

图1 说明:左半边是「直接改内核」——人钻进内核仓库里改文件,仓库被改得乱七八糟;右半边是「完整保留内核 + 外部 BSP」——内核原样不动,所有板级适配放在工程外部的 BSP / board 目录,干净解耦。两种范式一眼对比。
一、两种移植方式简单对比
方式一:直接修改内核源码(快速验证,适合学习调试)
我之前的移植博客,采用的就是这套思路:直接修改 kernel_liteos_m 仓库内部的 arch、kal、部分内核源文件,改完直接编译,快速把系统跑起来。
✅ 优点:
- 上手快,不需要先设计外部 BSP 隔离层;
- 可以直接阅读、修改内核内部逻辑,学习内核原理时非常直观;
- 不需要维护复杂的外部适配层,demo 验证效率很高。
❌ 致命短板(工程走到产品阶段就会暴露):
- 内核 Git 仓库被本地修改污染;执行
git status会出现大量改动,工作区不再干净; - 升级内核版本极其痛苦:上游
kernel_liteos_m更新了 bug 修复、新特性后,你不能简单地更新子模块,而要把之前所有修改手动重新移植一遍,极易遗漏补丁、引入隐性 bug; - 分不清哪些改动是「官方原生代码」、哪些是「我们为板子打的定制改动」;时间久了,连自己都搞不清哪些修改是必须的;
- 团队协作时,别人拉取代码容易误覆盖你的本地改动,问题难以复现。
定位:适合学习、Demo 快速验证,不建议直接作为量产工程模板。
方式二:完整物理保留内核仓库,内核零改动(通用推荐范式)
做法:kernel_liteos_m 完整 Git 仓库原样引入,不物理删除、不修改仓库内任何源文件,用 git status --short 校验内核工作区干净。
裁剪、板级适配不碰内核内部文件,全部通过两处外部手段完成:
- 外部配置头文件:工程侧
targets/xxx/target_config.h(或对应 board 目录下的配置头),通过宏开关关闭不需要的组件; - Makefile 编译源文件清单
C_SOURCES:只把真正需要参与编译的源文件纳入编译列表。磁盘上虽然全套源码都存在,但不会参与编译。
校验命令:
git status --short
如果内核子模块输出为空,就证明内核源码没有任何本地篡改。
✅ 优点:
- 内核与板级 BSP 完全解耦,所有板子差异收敛在工程自己的 BSP / board 目录;
- 升级 LiteOS-M 内核:只需要切换 git submodule 的 commit id,BSP 代码几乎不用改;
- 内核出现 bug,可以直接查官方
git log、官方提交,快速定位官方修复; - 团队协作干净,内核源码完全来自上游,本地改动全部可控、可追溯。
⚠️ 代价:
- 前期工程架构设计工作量更大,需要搭好外部 BSP 适配层;
- IDE 索引会看到磁盘上的全部源码,但很多文件并不参与编译,新手容易混淆「磁盘文件」和「实际链接进固件的文件」。
定位:量产 / 通用推荐范式,优先采用这套。
⚠️ 重点:这套不是行业强制法律标准,而是工程维护最佳实践。遇到紧急 bug 修复依然允许打补丁,但要以 patch 文件形式保存,不直接污染子模块工作区。
关键认知:磁盘源码冗余 ≠ 单片机固件冗余
电脑磁盘存放完整全套内核源码,完全不会增加单片机 Flash / RAM 的占用。
没有加入 Makefile 编译清单的源码,仅仅躺在硬盘里,不会参与编译过程。
再配合编译链接参数:
-ffunction-sections -fdata-sections
-Wl,--gc-sections
- 编译器把每一个函数、每一份数据切分成独立的段(section);
- 链接器执行垃圾回收
--gc-sections,把所有「没有被引用到」的段直接丢弃; - 最终
elf / bin固件里,只保留真正需要运行的代码。
类比:硬盘上是全部「原材料素材」;编译链接相当于漏斗筛选,只有被 Makefile 选中的代码,才进入下一步。实际工程里,最终固件的 text 段往往只有二十几 KB,和磁盘内核仓库有多大,没有任何关系。
图2 说明:用「漏斗」比喻编译前的筛选——磁盘上全套内核源码倒在漏斗上方,只有被 Makefile 编译清单选中的文件,才从漏斗口流下去进入编译;没被选中的,停在上面、不会进固件。
图2 讲的是「哪些文件参与编译」;下面图3 是更细的一步:编译之后,链接器还会再筛一遍。
图3 说明:用「筛子」比喻链接时的垃圾回收——编译出来的代码块一股脑倒进筛子,
--gc-sections就是筛网,只有被别处代码引用(“挂住”)的颗粒留下进固件,没被引用的渣滓直接漏掉丢弃。注意它和图2 的区别:图2 决定"进不进编译",图3 决定"编译后丢不丢未用段"。
比方:把编译出来的所有代码块倒进一张筛子,
--gc-sections就是那张筛网——只有被别处代码「挂住」(引用)的颗粒能留下来进固件;那些谁都没调用的零散渣滓,直接穿过筛网、掉进垃圾桶。所以即便某个文件被编译了,只要里面的函数没人调用,最终也不会占芯片空间。
二、真实商业产品的三条可行路线
方案 A:git submodule 引入完整内核,内核仓库零本地修改(推荐大多数项目)
kernel_liteos_m 作为 git 子模块引入,不在子模块目录做任何源码修改;所有板级适配、硬件修改,全部收敛到工程外部 BSP / board 目录。
裁剪依靠 Makefile 源文件清单 + target_config.h 配置宏实现。
✅ 收益:内核升级成本最低,bug 溯源简单。磁盘虽然存放全套源码,但不会全部编译进固件;PC 硬盘存储成本很低,真正稀缺的是 MCU 的 Flash、SRAM。
方案 B:物理拷贝筛选源码(部分公司项目在用)
从官方内核仓库,手动复制项目需要的 .c / .h,删除 testsuits、不需要的 components 等目录,工程不再携带完整 Git 仓库。
✅ 优点:工程目录文件少,磁盘目录清爽。
❌ 代价:后续内核版本升级,需要人工重新拷贝、比对源码,很容易漏掉官方 bug 修复,维护成本高。
方案 C:子模块完整引入,必要时打补丁(折中,内核必须修改时)
优先方案 A;只有官方内核确实存在 bug、必须修改内核源码才能跑通时,不要直接在子模块目录改代码。
正确做法:保存 .patch 补丁文件,由编译脚本自动应用补丁;保持子模块工作区原始干净,升级内核版本之后,重新 apply 补丁即可。
原则:能在 BSP / 配置宏解决的,绝不修改内核源码。万不得已要改内核,用 patch 补丁,不要直接污染 git 子模块。
图4 说明:用「三个并列方案面板」概括本章讲的三种工程路线,和上面方案 A/B/C 一一对应:左栏 = 完整子模块(模块齐全、不改动内核);中栏 = 物理裁剪(只留需要的文件、目录精简);右栏 = 子模块 + 补丁(仓库原样,额外贴一张 patch 补丁)。三条路怎么选,看上面三个方案的具体利弊。
三、总结
- 直接修改内核源码可以跑通工程,适合 Demo 与学习验证,但后续维护、内核升级代价很高。(对应我早期的移植博客)
- 磁盘源码冗余 ≠ 固件镜像冗余;源码只是电脑上的文件,不会自动进入芯片;固件大小由「参与编译链接的内容」决定。
- 工程三条路线:完整子模块零修改(优先) / 物理拷贝删减源码(目录清爽但维护麻烦) / 子模块 + patch 补丁(万不得已修改内核时)。
- 选择「完整保留内核源码、板级适配全部收敛到 BSP / board 目录」是大多数量产项目的首选;目的不是教条,而是贴近真实工业产品的可维护范式。
- 尽量不在内核仓库内直接修改源码;必须修改内核 bug 时,用 patch 补丁保存改动。
思考题
- 如果磁盘保存了完整的
components组件源码,但 Makefile 没有把它加入编译列表,这些组件会不会占用单片机 Flash?为什么?- 假如遇到 LiteOS-M 内核存在官方 bug,必须改动内核源文件才能让你的目标芯片跑通,你该如何处理?
(答案都在正文里——欢迎在评论区写下你的理解 👇)
更多推荐






所有评论(0)