内核编译基础:获取源码、配置、编译一条龙

说实话,很多刚接触内核的朋友,第一步就被卡住了。不是源码下载不下来,就是编译报错看不懂。今天我就把这套流程掰开揉碎了讲清楚。

内核编译说白了就四步:拿源码 → 选配置 → 编内核 → 编模块。每一步都有坑,我当年都踩过。

1. 获取内核源码

源码从哪来?两个主流渠道:

  • kernel.org:官方发布站,最干净
  • 发行版仓库:比如 Ubuntu 的 apt-get,带补丁

我个人习惯用 kernel.org 的长期支持版(LTS)。为什么?稳定。我在项目中遇到过某厂商 BSP 基于 4.19,结果自己手贱下了个 5.10 主线,驱动接口全变了,折腾两天才回滚。

我的建议:新手先用发行版自带的内核源码练手。比如 Ubuntu 执行 apt-get install linux-source,解压到 /usr/src 就能用。

下载后解压:

tar -xvf linux-6.1.tar.xz
cd linux-6.1

嗯,这里要注意:不要用 root 用户操作。我见过有人直接在 /root 下编译,权限乱套,最后 make clean 都报错。

2. 配置内核:make menuconfig

配置内核,说白了就是告诉编译器:哪些功能要,哪些不要。你想想看,一个内核支持几千种硬件,全编进去得有多大?

make menuconfig 是基于 ncurses 的图形界面。执行前先装依赖:

sudo apt-get install libncurses-dev

然后:

make menuconfig

界面长这样:

上下键移动,回车进入子菜单,空格切换状态:

  • [ ] 不编译
  • [M] 编译成模块
  • [*] 编译进内核

这里有个经验:不确定的选项就编成模块。我曾经为了省空间,把 USB 驱动直接编进内核,结果换了块主板 USB 控制器变了,内核直接 panic。编成模块的话,大不了 insmod 失败,系统还能进。

配置完会生成 .config 文件。你可以备份它:

cp .config config_my_board

下次直接 cp config_my_board .config 就能复用。

3. 编译内核:make zImage

配置好了,开始编译。嵌入式设备常用 zImage,它是压缩过的内核镜像。

make zImage -j4

-j4 表示用 4 个线程并行编译。我习惯用 nproc 获取 CPU 核心数:

make zImage -j$(nproc)

编译过程大概几分钟到半小时,取决于机器性能。我第一次编译时盯着屏幕看,生怕报错。其实大部分错误都是配置问题,比如:

  • 没装 gccmakeflexbison
  • 架构选错了(ARM 的配置用在 x86 上)
  • 磁盘空间不足(内核源码树挺大的)
注意:编译前确认当前架构。用 ARCH=armARCH=x86_64 指定。我见过有人用 x86 机器编 ARM 内核,忘了设 ARCH,编出来的镜像根本跑不了。

编译成功后会生成 arch/arm/boot/zImage(ARM 架构为例)。这个文件就是你要烧录的内核。

4. 编译模块:make modules

内核编完了,还有模块。模块就是那些你配置成 [M] 的驱动。

make modules -j$(nproc)

模块编译很快,因为内核已经编好了,模块只是链接一下。

编完后安装:

make modules_install

模块会被安装到 /lib/modules/$(uname -r)/ 目录下。每个模块一个 .ko 文件。

我遇到过一个问题:模块装好了,但 modprobe 说找不到。后来发现是 depmod 没跑。模块安装后一定要执行:

depmod -a

它会生成模块依赖关系文件。不然内核不知道哪个模块依赖哪个。

5. 完整编译流程总结

把上面几步串起来,一个完整的编译脚本大概长这样:

#!/bin/bash
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

make distclean
make menuconfig
make zImage -j$(nproc)
make modules -j$(nproc)
make modules_install
depmod -a

嗯,这里要注意:交叉编译工具链要提前装好。我习惯用 Linaro 的预编译工具链,省事。

6. 常见问题与避坑

问题 原因 解决
make menuconfig 报错 缺少 ncurses 库 apt-get install libncurses-dev
编译卡在某个文件 内存不足或磁盘满 检查 df -h 和 free -h
模块加载报 Unknown symbol 内核版本不匹配 重新编译内核和模块
zImage 生成但无法启动 设备树没配或配置错 检查 dts 文件
我的经验:每次修改配置后,先 make clean 再编译。别偷懒,不然可能遇到奇怪的问题。我曾经因为没 clean,编出来的内核里混了旧代码,调试了三天才发现。

7. 知识体系图

下面这张图概括了内核编译的完整流程和关键节点:

内核编译知识体系 获取源码 配置内核 编译内核 编译模块 kernel.org 发行版仓库 BSP 厂商提供 make menuconfig .config 文件 [*] / [M] / [ ] make zImage arch/arm/boot/ -j$(nproc) make modules .ko 文件 depmod -a 核心:配置决定编译内容,编译生成镜像+模块

这张图把四个步骤串起来了。你从上往下看,每一步都有对应的产出物。源码拿到手,配置选好,编译出 zImage 和 .ko 模块,最后安装到目标板。

好了,内核编译基础就讲到这里。这套流程我用了十年,每次换平台都这么干。你跟着走一遍,基本不会出大问题。


专注资料整理