3. 内核源码获取与结构分析:从 kernel.org 到 Kconfig/Makefile
好,咱们正式开始动手。这一章我带你做三件事:拿到源码、看懂骨架、摸清构建规则。这三步走顺了,后面裁剪和实时化才有根基。
3.1 从 kernel.org 获取 LTS 版本源码
源码去哪下?kernel.org,没第二个选择。我个人习惯只拿 LTS(Long Term Support) 版本,原因很简单:项目周期长,LTS 有 4-6 年维护,bug 修复和安全补丁持续跟进,不会中途断档。
当前推荐 LTS 版本(2025 年视角)
- 6.1.x — 新硬件支持好,实时补丁(PREEMPT_RT)已合入主线
- 5.15.x — 稳定,大量工业嵌入式项目在用
- 5.10.x — 老项目首选,资源占用低
下载方式很简单,我一般用 wget 直接拉 tarball:
# 以 6.1.80 为例
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.80.tar.xz
tar -xf linux-6.1.80.tar.xz
cd linux-6.1.80
小技巧:下载前先看 sha256sums.asc 校验文件,用 gpg --verify 验证签名。我曾经跳过这步,结果编译到一半发现源码被篡改过… 嗯,从那以后我再也不敢省了。
3.2 顶层目录结构解析
解压完,你看到一堆目录。别慌,我带你走一遍核心的。记住一句话:内核源码是按功能模块组织的,不是按文件大小。
| 目录 | 作用 | 我重点关注什么 |
|---|---|---|
arch/ |
体系结构相关代码 | 裁剪时只保留目标 CPU 架构,其余全删 |
drivers/ |
设备驱动,占源码 50% 以上 | 裁剪主战场,不用的驱动统统去掉 |
fs/ |
文件系统实现 | 根据根文件系统类型保留对应 fs |
kernel/ |
核心调度、进程管理、信号等 | 实时性优化主要动这里 |
mm/ |
内存管理 | 页面分配、SLAB、VMA 等 |
net/ |
网络协议栈 | 不需要网络功能的嵌入式设备直接砍掉 |
include/ |
全局头文件 | API 定义、数据结构声明 |
init/ |
内核初始化入口 | main.c 是起点 |
scripts/ |
编译、配置、分析工具脚本 | Kconfig 解析器、模块工具都在这里 |
你想想看,一个嵌入式设备可能只需要 ARM 架构、几个驱动、一种文件系统。其他目录里的代码,说白了就是编译时的负担。裁剪的核心思路就是:只编译你需要的。
3.3 Kconfig 与 Makefile 系统初探
内核的配置和编译不是靠手写 Makefile 的。它有一套自己的规则:Kconfig 定义“有什么选项”,Makefile 定义“怎么编译”。
3.3.1 Kconfig:配置选项的说明书
每个目录下都有一个 Kconfig 文件。比如 drivers/i2c/Kconfig 里定义了 I2C 子系统的所有开关。格式长这样:
config I2C
tristate "I2C support"
depends on HAS_IOMEM
help
I2C is a low-speed bus protocol...
config I2C_CHARDEV
tristate "I2C device interface"
depends on I2C
help
Provides a /dev/i2c-N interface...
关键字段:
- tristate — 三态:Y(编入内核)、M(模块)、N(不编译)
- depends on — 依赖关系,父选项不选,子选项不可见
- select — 反向依赖,选了 A 自动选 B
避坑:我曾经在裁剪时把 I2C 设成 N,结果 I2C_CHARDEV 自动消失。但某个传感器驱动依赖 I2C,编译直接报错。所以裁剪时一定要顺着 depends on 链条检查依赖。
3.3.2 Makefile:编译的执行者
同目录下的 Makefile 根据 Kconfig 生成的 .config 决定编译哪些文件。比如:
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
如果 CONFIG_I2C=y,i2c-core.o 会被编入内核;如果是 m,则编译成模块 i2c-core.ko;如果是 n,直接跳过。
这套机制的好处是:你只需要改 .config,Makefile 自动适配。不用手动改 Makefile,除非你要加新文件。
3.4 知识结构图:源码获取 → 目录解析 → 构建系统
下面这张图把本章的核心逻辑串起来了。我建议你把它打印出来贴在工位上,每次裁剪时对照着看。
3.5 实战建议:第一次怎么上手
别急着改代码。我建议你按这个顺序走一遍:
- 下载并解压一个 LTS 版本(比如 6.1.x)
- 浏览顶层目录,用
ls -l看看每个目录的大小 - 随便进一个驱动目录(比如
drivers/i2c),打开Kconfig和Makefile对照着看 - 运行
make menuconfig,看看图形界面里的选项怎么对应 Kconfig 里的定义
我的习惯:每次拿到新内核,我都会先 make defconfig 生成默认配置,然后 make menuconfig 手动关掉不需要的架构和驱动。这样能快速感知内核的“体重”。