3. 内核源码获取与配置:从下载到编译的完整链路
做嵌入式Linux,第一步就是搞定内核源码。这事儿看着简单,但版本选不对、配置漏项、编译链没对齐,后面全白干。我见过不少新手卡在「内核起不来」的坑里,最后发现是源码版本和工具链不匹配。
这一章,咱们把内核源码的获取、配置、编译整个流程走一遍。你跟着做,基本不会出大问题。
3.1 内核版本选择:别追新,要追稳
Linux内核版本号长这样:5.10.168。第一个数字是主版本,第二个是发布版本,第三个是补丁号。选哪个?我个人习惯用长期支持版(LTS)。
| 版本类型 | 特点 | 适用场景 |
|---|---|---|
| 主线版(Mainline) | 最新功能,更新快 | 开发测试、尝鲜 |
| 稳定版(Stable) | 修复Bug,相对稳定 | 一般产品原型 |
| 长期支持版(LTS) | 维护周期长(2-6年) | 量产产品、工业设备 |
我的建议:量产项目选LTS版本。比如5.10.x、6.1.x,社区维护时间长,驱动和工具链支持也成熟。别为了「新功能」选主线版,后面驱动移植会哭。
3.2 从kernel.org下载源码
官网是 https://www.kernel.org。进去后找「Latest LTS Version」那一栏。下载tarball包,别下patch文件。
# 下载5.10.168版本
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.168.tar.xz
# 校验完整性(强烈建议做)
sha256sum linux-5.10.168.tar.xz
# 对比官网的SHA256值
注意:下载后一定要校验哈希值。我曾经遇到过下载包损坏,编译到一半报错,排查了半天才发现是源码包的问题。浪费时间。
3.3 解压与目录结构分析
解压命令很简单:
tar -xvf linux-5.10.168.tar.xz
cd linux-5.10.168
解压后,你会看到一堆目录。我刚开始接触时也觉得眼花,但核心目录就那么几个:
- arch/:架构相关代码。ARM、ARM64、x86都在这里。移植时重点关注。
- drivers/:驱动代码。你写的驱动最终要放到这里。
- include/:头文件。内核API定义都在这里。
- kernel/:核心调度、进程管理。
- fs/:文件系统实现。
- Documentation/:文档。别忽略,很多坑这里都有说明。
核心逻辑:驱动移植主要动 arch/ 和 drivers/。其他目录一般不动。你想想看,改 kernel/ 里的调度代码?那是内核维护者的事。
下面这张图帮你理清内核源码的核心模块关系:
3.4 内核配置:make menuconfig
配置内核前,先确认环境。你需要安装 ncurses-dev 库,否则 menuconfig 跑不起来。
# Ubuntu/Debian
sudo apt-get install libncurses-dev
# 进入源码目录,开始配置
make menuconfig
界面出来后,你会看到一堆选项。别慌,核心配置项就这几个:
- General setup:通用设置,交叉编译工具链前缀在这里设。
- System Type:选择你的CPU架构(ARM、ARM64等)。
- Device Drivers:驱动配置。你要移植的驱动在这里勾选。
- File systems:文件系统支持。ext4、yaffs2、ubifs等。
- Networking support:网络协议栈。
避坑指南:我曾经在配置时漏掉了
CONFIG_DEVTMPFS,结果系统启动后 /dev 目录是空的,设备节点一个都没有。排查了一整天。所以,记得在 Device Drivers → Generic Driver Options 里勾上 Maintain a devtmpfs filesystem。
配置完成后,保存退出。配置文件会生成在源码根目录的 .config 文件里。你可以备份一份:
cp .config config_my_board
3.5 编译内核与模块
配置好了,开始编译。这里分两步:编译内核镜像和编译可加载模块。
# 设置交叉编译环境(以ARM64为例)
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# 编译内核镜像
make -j4 Image
# 编译设备树
make -j4 dtbs
# 编译模块
make -j4 modules
# 安装模块到指定目录
make modules_install INSTALL_MOD_PATH=./modules_install
编译完成后,你会得到:
arch/arm64/boot/Image:内核镜像arch/arm64/boot/dts/:设备树文件(.dtb)modules_install/lib/modules/:编译好的内核模块
注意:编译时加
-jN 参数(N为CPU核心数+1)能加速。但别贪多,我试过 -j32 在8核机器上,结果内存爆了,编译直接OOM。一般 -j4 或 -j8 就够。
3.6 常见问题与排查
编译过程中可能会遇到各种错误。我列几个常见的:
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
找不到 ncurses.h |
缺少 libncurses-dev |
sudo apt-get install libncurses-dev |
编译报 undefined reference |
配置项依赖未选 | 检查 .config,补全依赖 |
| 生成的内核无法启动 | 架构或设备树不匹配 | 确认 ARCH 和 CROSS_COMPILE 正确 |
模块加载报 Invalid module format |
内核版本与模块版本不一致 | 重新编译模块,确保与内核同源码 |
核心总结:内核源码获取与配置,说白了就是「选对版本 → 下载校验 → 配置裁剪 → 编译输出」这四步。每一步都有坑,但只要你按流程走,遇到问题先看 Documentation/ 和 .config,基本都能解决。
嗯,这一章的内容就到这儿。你先把内核编译通过,后面驱动移植才有得玩。