3. 内核配置与编译系统

内核裁剪,说白了就是给Linux内核做「瘦身手术」。你想想看,一个通用内核里塞了几千个驱动和功能模块,但你的ARM板子可能只需要其中不到10%。把不需要的砍掉,内核就能跑得更快、占得更少、启动时间更短。

我在项目里遇到过一块Flash只有8MB的工业控制板,通用内核根本塞不进去。那次之后,我算是把内核裁剪这门手艺彻底练熟了。

make menuconfig:图形化配置入门

配置内核最常用的工具就是 make menuconfig。它基于ncurses库,在终端里给你一个图形界面。操作起来很简单:

# 进入内核源码目录
cd linux-5.10.y

# 加载默认配置(针对ARM架构)
make ARCH=arm defconfig

# 启动图形化配置界面
make ARCH=arm menuconfig

界面里你会看到三层结构:

  • 主菜单:按功能分类的大项,比如General setup、Device Drivers
  • 子菜单:按Enter进入,里面是具体的配置项
  • 配置项:三种状态——[*](built-in)、[M](模块)、[ ](禁用)

操作小技巧:按 / 键可以搜索配置项名称,输入 CONFIG_MMC 就能快速定位SD卡驱动。我经常用这个功能,比手动翻菜单快多了。

内核模块 vs built-in:到底怎么选?

这是裁剪时最纠结的问题。我画了一张图帮你理清思路:

内核模块 vs built-in 决策流程 某个功能/驱动 启动时必须用? built-in [*] 是 模块 [M] 否 频繁加载/卸载? 调试/开发阶段? 建议 built-in 建议模块 核心原则:根文件系统必须的 → built-in;可热插拔/调试用的 → 模块

我个人的经验法则很简单:

场景 推荐方式 原因
根文件系统驱动(MMC/SD、NAND Flash) built-in 内核启动时需要挂载根文件系统,模块还没加载
网络协议栈、调度器核心 built-in 系统运行的基础,不能卸载
USB、WiFi、蓝牙驱动 模块 设备可能热插拔,按需加载
调试工具、测试驱动 模块 开发阶段频繁修改,模块化方便替换
不常用的硬件驱动 禁用 裁剪掉,节省空间

我曾经踩过的坑:有一次我把SD卡驱动配成了模块,结果内核启动后根文件系统在SD卡上,模块还没加载,系统直接panic了。嗯,从那以后我记住了——根文件系统所在的存储设备驱动,必须built-in。

裁剪原则与最小系统概念

什么叫最小系统?就是能让你的ARM板子正常启动、跑起应用程序的最简内核配置。我总结了一套「三步裁剪法」:

  1. 先跑起来:用默认配置编译,确认板子能正常启动
  2. 再砍掉:逐项禁用不需要的功能,每改一次就编译测试
  3. 最后优化:把模块化的驱动按需加载,进一步缩小内核体积

裁剪时记住这几个原则:

  • 架构相关不能动:CPU型号、内存映射、中断控制器这些,动了就起不来
  • 启动路径必须通:从bootloader到内核解压,再到挂载根文件系统,这条链上的驱动一个都不能少
  • 按需配置驱动:你的板子上有什么硬件,就配什么驱动。多一个都不要
  • 文件系统支持要精简:只用你实际用的文件系统类型,比如ext4、squashfs

最小系统清单(ARM Cortex-A系列):

  • CPU架构:ARMv7-A或ARMv8-A
  • 定时器:ARM Generic Timer
  • 中断控制器:GIC v2/v3
  • 串口驱动:用于控制台输出
  • 存储驱动:MMC/SD或NAND Flash
  • 根文件系统:ext4或squashfs
  • 网络协议栈:TCP/IP(如果需要网络)

保存与加载配置文件

配置好内核后,一定要保存配置。我见过太多人配了半天,结果忘了保存,下次从头再来。

# 保存当前配置到默认位置
make ARCH=arm savedefconfig

# 或者手动复制
cp .config arch/arm/configs/my_board_defconfig

# 下次加载
make ARCH=arm my_board_defconfig

savedefconfig 命令会生成一个精简版的配置文件,只保留与默认值不同的选项。这个文件可读性更好,也方便版本管理。

我个人习惯把不同阶段的配置都保存下来:

配置文件 用途
defconfig 板级默认配置,用于日常开发
minimal_defconfig 最小系统配置,用于生产环境
debug_defconfig 开启调试选项,用于问题排查

版本管理小技巧:把 defconfig 文件提交到Git仓库,每次修改都记录变更。这样出了问题可以快速回退到上一个可用版本。我在团队里推行这个做法后,再也没出现过「谁改了配置导致起不来」的扯皮情况。

最后提醒一句:裁剪不是一锤子买卖。随着项目推进,你可能需要添加新功能、支持新硬件。每次修改配置后,都重新编译测试一遍。别偷懒,这个习惯能帮你省下大把调试时间。