一个被严重低估的嵌入式系统微内核!

strongerHuang 2025-10-30 08:00
来源 | 嵌入式大杂烩
 

今天分享一个专为嵌入式系统设计的小型操作系统内核LK (Little Kernel) 。

一、LK简介

1.1 LK是什么

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

https://github.com/littlekernel/lk

一个被严重低估的嵌入式系统微内核!图1

与传统的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采用了经典的分层架构设计,从下到上分为五层:

一个被严重低估的嵌入式系统微内核!图2

这种分层设计的核心思想是关注点分离

  • 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

构建系统会自动解析依赖关系,确保模块按正确顺序编译和链接。这种方式的优势:

  • 模块可以按需加载,减小最终镜像大小
  • 依赖关系明确,避免循环依赖
  • 便于单元测试和模块复用

三、核心机制

3.1 线程调度机制

3.1.1 核心数据结构

LK的线程调度器是一个优先级抢占式调度器,支持32个优先级级别。线程结构体定义如下:

一个被严重低估的嵌入式系统微内核!图4

3.1.2 调度器实现

调度器的核心是就绪队列优先级位图

一个被严重低估的嵌入式系统微内核!图5

调度算法流程:

一个被严重低估的嵌入式系统微内核!图6

核心代码片段:

一个被严重低估的嵌入式系统微内核!图7

3.1.3 时间片轮转

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

一个被严重低估的嵌入式系统微内核!图8
  • O(1)时间复杂度:通过位图和优先级队列实现常数时间调度
  • 支持多核:每个CPU独立的调度器
  • 低延迟:关键路径代码精简,上下文切换开销小

3.2 分层初始化机制

3.2.1 初始化级别定义

LK定义了多个初始化级别,确保系统组件按正确顺序初始化:

一个被严重低估的嵌入式系统微内核!图9

3.2.2 初始化宏机制

通过宏注册初始化函数:

一个被严重低估的嵌入式系统微内核!图10

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

一个被严重低估的嵌入式系统微内核!图11

3.2.3 启动流程

一个被严重低估的嵌入式系统微内核!图12

关键点:

  1. thread_init_early:在没有堆的情况下初始化基本线程结构
  2. heap_init之前:不能使用malloc,只能用静态分配
  3. kernel_init:初始化线程系统、定时器、端口等
  4. thread_become_idle:主线程变成idle线程,启用中断,开始调度

3.3 模块化构建系统

3.3.1 模块定义方式

每个模块通过rules.mk定义自己:

一个被严重低估的嵌入式系统微内核!图13

四、快速开始

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:

一个被严重低估的嵌入式系统微内核!图14

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 ------------

声明:内容取材于网络,仅代表作者观点,如有内容违规问题,请联系处理。 
嵌入式系统
more
DigiKey 应用探索站 | 嵌入式系统和微控制器技术【第一趴】
告别内存碎片!嵌入式系统内存池完美解决方案
分享一款嵌入式系统内存泄漏检测利器:MTrace
分享一款专为嵌入式系统设计的HTTP库
嵌入式系统中的极简二维码生成方案!
一个被严重低估的嵌入式系统微内核!
嵌入式系统软件代码常见的容错设计
RISC-V 生态专区 “嵌入式系统与智能终端” Workshop圆满落幕:隼瞻科技携手战略合作伙伴共探产业新路径
基于AI的嵌入式系统的功能安全设计
专为嵌入式系统设计的轻量级框架
Copyright © 2025 成都区角科技有限公司
蜀ICP备2025143415号-1
  
川公网安备51015602001305号