今天分享一个专为嵌入式系统设计的小型操作系统内核LK (Little Kernel) 。
一、LK简介
1.1 LK是什么
LK (Little Kernel) 是一个专为嵌入式系统设计的小型操作系统内核,诞生于Google工程师Travis Geiselbrecht之手。它最初作为Android设备的bootloader而广为人知,如今已经发展成为一个功能完整的嵌入式操作系统内核,被广泛应用于各类开源和商业项目中。
https://github.com/littlekernel/lk

与传统的RTOS(如FreeRTOS、RT-Thread)不同,LK从设计之初就考虑了现代嵌入式系统的复杂性需求:
-
SMP多核支持:原生支持多核处理器 -
虚拟内存管理:可选的完整MMU支持 -
广泛的架构支持:从8位单片机到64位应用处理器
1.2 LK在嵌入式领域的定位
LK处于传统RTOS和Linux之间的一个独特位置。它比FreeRTOS更强大,提供了完整的虚拟内存支持和多核调度;但比Linux更轻量,启动时间以毫秒计,内核代码量仅数万行。这使它成为以下场景的理想选择:
-
Bootloader开发:需要快速启动和硬件初始化 -
固件开发:需要完整OS功能但对资源敏感 -
嵌入式应用:需要在资源受限环境运行复杂逻辑 -
学习内核原理:代码简洁,适合理解OS设计
1.3 为什么推荐这个项目
LK项目有几个显著特点使其成为学习的绝佳范本:
1. 架构设计清晰:严格的分层设计和模块化架构,Arch-Platform-Target三层抽象极具代表性。
2. 代码质量高:代码遵循统一的编码规范,注释详尽,MIT许可证友好。
3. 工程实践优秀:构建系统设计精巧,模块依赖管理自动化,跨平台编译简单。
4. 实际应用广泛:被用于数百万Android设备的bootloader中,经过充分验证。
5. 可扩展性强:模块化设计使得添加新功能、移植新平台都非常容易。
通过拆解LK,我们不仅能学到一个RTOS该如何设计,更能理解现代嵌入式软件工程的最佳实践。
二、整体架构设计
2.1 顶层架构
LK采用了经典的分层架构设计,从下到上分为五层:

这种分层设计的核心思想是关注点分离:
-
Arch层:处理CPU指令集相关的底层操作 -
Platform层:处理SoC相关的外设驱动 -
Target层:处理具体电路板的配置 -
Kernel层:提供操作系统核心功能 -
App层:实现具体应用逻辑
2.2 目录结构解析
lk/
├── arch/ # 架构层:各CPU架构的实现
│ ├── arm/ # ARM 32位架构
│ ├── arm64/ # ARM 64位架构
│ ├── riscv/ # RISC-V架构
│ └── x86/ # x86架构
├── platform/ # 平台层:各SoC平台的驱动
│ ├── stm32f4xx/ # STM32F4系列
│ ├── rp20xx/ # 树莓派Pico
│ └── qemu-virt-*/ # QEMU虚拟平台
├── target/ # 目标层:具体开发板配置
├── kernel/ # 内核层:核心OS功能
│ ├── thread.c # 线程管理和调度器
│ ├── mutex.c # 互斥锁
│ ├── timer.c # 内核定时器
│ └── vm/ # 虚拟内存子系统
├── lib/ # 库层:各种功能库
│ ├── libc/ # C标准库实现
│ ├── heap/ # 堆内存管理
│ └── console/ # 控制台
├── top/ # 系统启动入口
│ └── main.c # lk_main()入口
├── project/ # 项目配置:定义编译什么
└── engine.mk # 构建引擎:核心构建逻辑
这种目录结构体现了高内聚、低耦合的设计原则。每一层都可以独立开发和测试,新增平台支持只需添加对应目录下的文件。
2.3 模块间交互
LK使用依赖注入的方式管理模块间的交互。每个模块通过rules.mk声明自己的依赖:

构建系统会自动解析依赖关系,确保模块按正确顺序编译和链接。这种方式的优势:
-
模块可以按需加载,减小最终镜像大小 -
依赖关系明确,避免循环依赖 -
便于单元测试和模块复用
三、核心机制
3.1 线程调度机制
3.1.1 核心数据结构
LK的线程调度器是一个优先级抢占式调度器,支持32个优先级级别。线程结构体定义如下:

3.1.2 调度器实现
调度器的核心是就绪队列和优先级位图:

调度算法流程:

核心代码片段:

3.1.3 时间片轮转
LK实现了基于定时器的时间片轮转:

-
O(1)时间复杂度:通过位图和优先级队列实现常数时间调度 -
支持多核:每个CPU独立的调度器 -
低延迟:关键路径代码精简,上下文切换开销小
3.2 分层初始化机制
3.2.1 初始化级别定义
LK定义了多个初始化级别,确保系统组件按正确顺序初始化:

3.2.2 初始化宏机制
通过宏注册初始化函数:

编译器会将所有初始化结构体收集到.lk_init段,启动时遍历执行:

3.2.3 启动流程

关键点:
-
thread_init_early:在没有堆的情况下初始化基本线程结构 -
heap_init之前:不能使用malloc,只能用静态分配 -
kernel_init:初始化线程系统、定时器、端口等 -
thread_become_idle:主线程变成idle线程,启用中断,开始调度
3.3 模块化构建系统
3.3.1 模块定义方式
每个模块通过rules.mk定义自己:

四、快速开始
4.1 快速开始示例
4.1.1 编译QEMU ARM项目
# 克隆仓库
git clone https://github.com/littlekernel/lk.git
cd lk
# 编译QEMU ARM Cortex-A15项目
make qemu-virt-arm-a15
# 运行(需要安装qemu-system-arm)
make qemu-virt-arm-a15 qemu
4.1.2 创建自定义应用
app/myapp/myapp.c:

app/myapp/rules.mk:
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
MODULE_SRCS += $(LOCAL_DIR)/myapp.c
MODULE_DEPS += lib/console
include make/module.mk
project/myproject.mk:
TARGET := qemu-virt-arm-a15
MODULES += app/myapp
编译运行:
make myproject
make myproject qemu
相关资源:
-
LK GitHub仓库:https://github.com/littlekernel/lk -
LK文档:https://github.com/littlekernel/lk/tree/master/docs
------------ END ------------