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/ 里的调度代码?那是内核维护者的事。

下面这张图帮你理清内核源码的核心模块关系:

Linux内核源码核心模块关系图 Linux内核源码核心模块关系 用户空间应用程序 系统调用接口 (kernel/sys.c) 内核核心层 进程调度 (kernel/sched/) 内存管理 (mm/) 文件系统 (fs/) 设备驱动层 (drivers/) 字符设备 | 块设备 | 网络设备 | 总线驱动 硬件抽象层 (arch/) 移植重点

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,基本都能解决。

嗯,这一章的内容就到这儿。你先把内核编译通过,后面驱动移植才有得玩。