内核编译基础:获取源码、配置、编译一条龙
说实话,很多刚接触内核的朋友,第一步就被卡住了。不是源码下载不下来,就是编译报错看不懂。今天我就把这套流程掰开揉碎了讲清楚。
内核编译说白了就四步:拿源码 → 选配置 → 编内核 → 编模块。每一步都有坑,我当年都踩过。
1. 获取内核源码
源码从哪来?两个主流渠道:
- kernel.org:官方发布站,最干净
- 发行版仓库:比如 Ubuntu 的 apt-get,带补丁
我个人习惯用 kernel.org 的长期支持版(LTS)。为什么?稳定。我在项目中遇到过某厂商 BSP 基于 4.19,结果自己手贱下了个 5.10 主线,驱动接口全变了,折腾两天才回滚。
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)
编译过程大概几分钟到半小时,取决于机器性能。我第一次编译时盯着屏幕看,生怕报错。其实大部分错误都是配置问题,比如:
- 没装
gcc、make、flex、bison - 架构选错了(ARM 的配置用在 x86 上)
- 磁盘空间不足(内核源码树挺大的)
ARCH=arm 或 ARCH=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. 知识体系图
下面这张图概括了内核编译的完整流程和关键节点:
这张图把四个步骤串起来了。你从上往下看,每一步都有对应的产出物。源码拿到手,配置选好,编译出 zImage 和 .ko 模块,最后安装到目标板。
好了,内核编译基础就讲到这里。这套流程我用了十年,每次换平台都这么干。你跟着走一遍,基本不会出大问题。