内核源码获取与配置:从kernel.org到你的开发板
做嵌入式Linux开发,第一步就是拿到内核源码。这事儿听起来简单,但里面坑不少。我见过不少新手直接从网盘下载一个“万能内核包”,结果编译出来板子死活起不来——说白了,版本不对,配置也不对。
这一章,我们就从最正统的源头开始:kernel.org。我会带你走一遍获取源码、理解目录结构、搞懂Kconfig/Makefile这套配置系统,最后亲手用make menuconfig做一次图形化配置。
从kernel.org获取Linux内核源码
官方下载地址就一个:https://www.kernel.org。进去之后你会看到几个版本分类:
| 版本类型 | 说明 | 适用场景 |
|---|---|---|
| Mainline | 主线最新版,Linus Torvalds直接维护 | 尝鲜、新硬件支持、学习 |
| Stable | 主线基础上修bug的稳定版 | 产品开发首选 |
| Longterm | 长期支持版,维护周期数年 | 嵌入式产品、工业设备 |
| Next | 开发中的代码,可能不稳定 | 内核开发者、测试 |
我个人习惯用Longterm版本做嵌入式项目。比如现在常用的5.10.y或6.1.y,社区支持好,驱动也全。你想想看,产品一卖就是三五年,选个长期支持版省心得多。
下载命令很简单:
# 以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/
sha256sum --check,几秒钟的事,能省几小时。
内核源码目录结构解析
解压完你会看到几十个目录。第一次接触的人可能会懵——这么多文件夹,从哪看起?
别急,核心目录其实就这几个:
| 目录 | 作用 | 我重点关注什么 |
|---|---|---|
| arch/ | 体系结构相关代码 | arch/arm/、arch/arm64/、arch/x86/ |
| drivers/ | 设备驱动,占源码一半以上 | drivers/net/、drivers/i2c/、drivers/spi/ |
| fs/ | 文件系统实现 | fs/ext4/、fs/proc/、fs/sysfs/ |
| include/ | 内核头文件 | include/linux/、include/uapi/ |
| kernel/ | 核心调度、进程管理 | 调试时经常看kernel/panic.c |
| mm/ | 内存管理 | 调内存泄漏时必看 |
| net/ | 网络协议栈 | net/ipv4/、net/wireless/ |
| scripts/ | 编译、配置辅助脚本 | scripts/kconfig/ 配置系统核心 |
嗯,这里要注意:arch/下面每个CPU架构都有自己的一套启动代码、内存布局、中断处理。你做嵌入式,ARM或RISC-V的话,大部分时间都在arch/arm/或arch/arm64/里折腾。
我举个例子。有一次调试一个ARM板子的启动卡死问题,最后定位到是arch/arm/mach-xxx/下面的板级初始化代码里,GPIO复用配置错了。这种问题,不懂目录结构根本无从下手。
配置系统(Kconfig/Makefile)原理
内核的配置系统,说白了就是一套“选择题生成器”。Kconfig定义题目,Makefile根据答案决定编译什么。
Kconfig:定义“有什么选项”
每个目录下都有一个Kconfig文件。比如drivers/i2c/Kconfig里会写:
config I2C_CHARDEV
tristate "I2C device interface"
help
Say Y here to enable I2C character device interface.
这个选项允许用户空间通过/dev/i2c-N访问I2C设备。
这里tristate表示三种状态:Y(编译进内核)、M(编译成模块)、N(不编译)。
Kconfig还支持depends on(依赖)、select(自动选中)、default(默认值)等关键字。我在项目中遇到过最坑的情况是:选了一个驱动,它自动select了另一个驱动,结果那个驱动依赖的硬件不存在,编译出来内核直接panic。
select关键字,一定要追查它选了什么东西。
Makefile:决定“怎么编译”
Kconfig定义完选项,Makefile根据配置结果决定编译行为:
# drivers/i2c/Makefile
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
如果CONFIG_I2C_CHARDEV=y,就编译i2c-dev.o并链接进内核;如果是m,就编译成独立的.ko模块;如果是n,就跳过。
这个机制非常优雅。你想想看,几千个驱动,每个都按这个规则来,配置系统自动管理依赖和编译顺序。
make menuconfig 图形化配置实战
理论说完了,上手实操。配置内核最常用的命令就是make menuconfig。
准备工作
先确保安装了ncurses库:
sudo apt-get install libncurses-dev
然后进入内核源码目录,执行:
make menuconfig
你会看到一个蓝底白字的图形界面。操作很简单:
- 方向键:上下移动
- Enter:进入子菜单
- Y:选中(编译进内核)
- M:选中为模块
- N:取消选中
- ?:查看帮助
- /:搜索选项
实战:配置一个最小化ARM内核
假设我们要为ARM Cortex-A7的板子配置内核:
- 选择架构:进入
General setup→Cross-compiler tool prefix,填arm-linux-gnueabihf- - 选择CPU类型:
System Type→ 选择你的SoC厂商(比如ARM Ltd.→ARMv7 based platforms) - 使能必要的驱动:
Device Drivers→ 勾选I2C、SPI、GPIO、MMC/SD等 - 文件系统:
File systems→ 勾选ext4、proc、sysfs - 网络:
Networking support→ 勾选TCP/IP、Ethernet
配置完成后,按Tab键选择Save,默认保存为.config文件。
核心知识点:.config文件就是内核配置的“答案本”。每一行都是一个CONFIG_XXX=y/m/n。你可以直接编辑这个文件,但更推荐用menuconfig,因为它会自动处理依赖关系。
配置系统核心流程
下面这张图展示了从Kconfig到最终编译的完整链路:
常用配置技巧
- 搜索功能:按
/键输入关键字,比如搜I2C,会列出所有相关选项及其路径。我在调试一个触摸屏驱动时,就是靠搜索找到CONFIG_TOUCHSCREEN_GT9XX的。 - 快速加载默认配置:
make defconfig生成架构默认配置;make tinyconfig生成最小配置。 - 保存配置片段:
make savedefconfig会把当前配置精简成最小化版本,方便版本管理。
make defconfig 生成基础配置,再用 make menuconfig 微调。最后 make savedefconfig 把精简配置提交到Git仓库。这样同事拉下来后,make defconfig 再 make 就能复现我的环境。
小结
这一章我们走通了内核源码的获取、目录结构、配置系统原理和实战操作。核心就三件事:从kernel.org拿源码、看懂Kconfig/Makefile的配合、用menuconfig生成.config。