来源 | 嵌入式大杂烩

今天分享一个专为嵌入式系统设计的小型操作系统内核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 启动流程

关键点:

  1. thread_init_early:在没有堆的情况下初始化基本线程结构

  2. heap_init之前:不能使用malloc,只能用静态分配

  3. kernel_init:初始化线程系统、定时器、端口等

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

图片

●专栏《嵌入式工具

●专栏《嵌入式开发》

●专栏《Keil教程》

●嵌入式专栏精选教程

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

点击“阅读原文”查看更多分享。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐