1. 内核编译与启动:从源码下载到内核启动的全流程

说实话,很多搞内核开发的朋友,第一步就卡在编译上。不是缺依赖,就是配置选项选错,折腾半天连个内核都起不来。我当年刚入行时也踩过不少坑,有一次编译出来的内核直接 panic,连错误日志都没来得及看——嗯,从那以后我养成了几个好习惯,今天一并分享给你。

1.1 源码下载:选对版本,少走弯路

内核源码的获取方式有好几种,我个人最推荐用 git 拉取主线仓库。为什么?因为你可以随时切换分支、查看历史提交,调试时特别方便。

推荐源码获取方式

  • Git 主线仓库:git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  • 稳定版 tarball:从 kernel.org 下载 linux-x.y.z.tar.xz
  • 发行版源码包:Ubuntu 用 apt-get source linux-image-$(uname -r)

我的习惯:调试用主线最新 RC 版,生产环境用 LTS 版本。曾经有一次我图省事直接用了发行版自带的源码包,结果发现打了大量补丁,跟主线对不上,调试时各种诡异行为——从那以后我再也不偷懒了。

1.2 内核配置:选项多到眼花,怎么选?

内核配置选项有上万个,你不可能一个个看完。我一般分三步走:

  1. 基于当前系统配置:make oldconfig 或 make localmodconfig
  2. 按需微调:make menuconfig 图形化界面
  3. 保存 .config:备份一份,方便回退

localmodconfig 这个命令特别实用。它会扫描你当前系统加载的模块,只保留这些模块的配置项。我第一次用的时候,配置项从一万多个直接降到两千多,编译时间从半小时缩短到五分钟。你想想看,省下来的时间干点啥不好?

注意:localmodconfig 生成的配置只包含当前硬件支持的驱动。如果你换了机器或者加了新设备,记得重新跑一遍。我曾经在笔记本上编译完内核,换到台式机上启动时发现网卡驱动没编进去——尴尬不?

1.3 编译:耐心等待,但别干等

配置搞定后,编译就简单了。核心命令就几个:

# 清理旧编译产物
make clean

# 编译内核和模块
make -j$(nproc)

# 编译模块
make modules

# 安装模块
sudo make modules_install

# 安装内核
sudo make install

-j$(nproc) 这个参数很关键。它会让 make 用你 CPU 的所有核心并行编译。我见过有人用单核编译 5.10 内核,等了快一个小时。用并行编译,16 核机器上也就 3-5 分钟。

编译阶段 耗时(16核) 常见问题
配置生成 几秒 依赖缺失(如 flex、bison)
内核编译 3-5 分钟 内存不足(建议 4GB+)
模块编译 1-2 分钟 头文件路径错误
模块安装 几秒 权限不足(需 sudo)
内核安装 几秒 /boot 空间不足

1.4 GRUB 配置:让新内核跑起来

内核安装完成后,GRUB 会自动检测并添加新条目。但有时候它不听话,你得手动更新:

# 更新 GRUB 配置
sudo update-grub

# 或者手动编辑 /etc/default/grub
# 修改 GRUB_DEFAULT 指定默认启动项
# 修改 GRUB_TIMEOUT 调整等待时间

# 应用修改
sudo grub-mkconfig -o /boot/grub/grub.cfg

避坑指南:我曾经在调试时同时装了 5 个内核版本,结果 GRUB 菜单长得跟购物清单似的。后来我养成了两个习惯:一是编译前用 make kernelrelease 确认版本号,二是装完新内核后立即删掉旧内核(sudo apt-get autoremove)。

1.5 启动验证:确认内核跑起来了

重启后,用以下命令确认新内核是否生效:

# 查看当前内核版本
uname -r

# 查看内核启动参数
cat /proc/cmdline

# 查看内核日志(dmesg)
dmesg | grep "Linux version"

# 查看模块加载情况
lsmod | head -20

如果系统起不来,别慌。重启时按住 Shift(或 Esc)进入 GRUB 菜单,选择旧内核启动。然后检查 /var/log/kern.log 或 dmesg 输出,看看是哪个驱动炸了。

1.6 全流程知识图谱

下面这张图把整个流程串起来了,建议你保存下来对照着操作:

内核编译与启动全流程 源码下载 内核配置 内核编译 模块安装 GRUB 配置 git clone / tarball / 发行版源码 推荐主线 git 仓库,方便切换分支 make menuconfig / localmodconfig localmodconfig 可大幅减少配置项 make -j$(nproc) / make modules 并行编译,节省大量时间 sudo make modules_install 安装到 /lib/modules/ 目录 update-grub / grub-mkconfig 生成 GRUB 菜单,选择新内核启动 关键要点 • 源码用 git 拉取,方便调试 • 配置用 localmodconfig 省时间 • 编译用 -j$(nproc) 并行加速 • 安装后记得 update-grub • 启动失败用旧内核回退 • 检查 dmesg 定位问题 • 备份 .config 方便回退 • 删除旧内核释放 /boot 空间 • 调试用主线,生产用 LTS • 模块依赖用 lsmod 检查 • 内核参数用 /proc/cmdline 查看 • 版本确认用 uname -r • 日志排查用 /var/log/kern.log • 多版本管理用 GRUB_DEFAULT

1.7 常见问题与避坑

最后,我把这些年遇到过的典型问题列出来,你碰到了可以直接对照:

问题现象 可能原因 解决方案
编译报错 flex: command not found 缺少 flex、bison 等工具 sudo apt-get install flex bison
启动时 kernel panic 驱动配置错误或模块缺失 用旧内核启动,检查 dmesg
GRUB 菜单没有新内核 未执行 update-grub sudo update-grub
模块加载失败 内核版本与模块版本不匹配 重新编译模块或检查 depmod
/boot 空间不足 旧内核太多 sudo apt-get autoremove 清理

嗯,这一章的内容就到这里。内核编译这件事,说白了就是熟能生巧。多编译几次,你自然就知道哪些选项该开、哪些该关、哪些坑要绕开。下次遇到问题,记得先看 dmesg,它比任何文档都诚实。