3. 内核裁剪基础:关闭无用驱动与子系统

内核裁剪这事儿,说白了就是给系统做减法。车载硬件资源就那么点,你塞一堆用不上的驱动进去,不光浪费Flash空间,还拖慢启动速度。我刚开始做车载项目时,就吃过这个亏——编译出来的内核镜像快20MB,烧进去发现根本跑不起来。

嗯,今天咱们就聊聊怎么把内核瘦下来。核心就三件事:关掉没用的驱动和子系统、搞懂模块和built-in怎么选、最后看看裁剪前后到底差多少。

3.1 关闭无用驱动与子系统

车载系统里,硬件是固定的。你想想看,一个车载娱乐主机,哪来的Wi-Fi网卡?哪来的蓝牙键盘?这些驱动统统可以关掉。

我个人习惯,先跑一遍 make menuconfig,然后按这几个维度去扫:

  • 架构无关的驱动:比如显卡驱动(DRM)、声卡驱动(ALSA)、网络驱动。车载上只用得到特定的几款,其他的全关。
  • 文件系统支持:车载一般用ext4、squashfs、ubifs。像什么btrfs、xfs、ntfs,用不上就关。
  • 网络协议栈:车载不需要IPv6、IPSec、Netfilter全套。我一般只留IPv4和基本的TCP/UDP。
  • 电源管理子系统:车载有自己的一套电源管理,内核自带的ACPI、APM这些可以关掉。
我的经验: 别一上来就猛关。先编译一个全功能版本跑起来,然后逐个模块关掉测试。我曾经一次性关了20多个选项,结果系统起不来,排查了整整一天。

下面这张图,是我整理的内核裁剪核心逻辑:

内核裁剪决策流程 原始内核配置 关闭无用驱动 模块 vs built-in 裁剪子系统 GPU/声卡/网卡驱动 文件系统(btrfs等) 频繁使用→built-in 按需加载→模块 电源管理子系统 网络协议栈精简 裁剪后的内核

3.2 内核模块与built-in的选择策略

这里有个经典问题:某个驱动,到底编译成模块(.ko)还是直接编进内核(built-in)?

我的判断标准很简单:

  • 启动必须用的:比如存储控制器、根文件系统驱动、串口调试。这些必须built-in。否则内核都挂不上根文件系统,模块从哪加载?
  • 按需加载的:比如USB设备驱动、音频编解码器、显示控制器。这些做成模块,系统启动后再加载,能减小内核镜像体积。
  • 调试用的:比如各种测试驱动、debugfs。做成模块,调试时加载,发布时直接删掉。
核心原则: built-in 增大镜像体积但减少启动依赖;模块减小镜像体积但需要额外的文件系统和加载时间。车载上,我倾向于把稳定、常用的驱动 built-in,不常用的做成模块。

举个例子,车载上的显示驱动:

# 显示控制器(必须built-in,否则无法显示开机画面)
CONFIG_DRM=y
CONFIG_DRM_ROCKCHIP=y

# 触摸屏驱动(可以做成模块,用户登录后才需要)
CONFIG_TOUCHSCREEN_GT9XX=m

# 音频驱动(做成模块,系统启动后加载)
CONFIG_SND_SOC_ROCKCHIP=m

我曾经在一个项目里,把所有驱动都做成模块,结果内核镜像只有3MB,但根文件系统里塞了20多个.ko文件。启动时一个个加载,反而比全built-in还慢。后来我学乖了——启动路径上的驱动,一律built-in。

3.3 裁剪前后体积对比

光说不练假把式。咱们看一组真实数据。这是我之前做的一个车载信息娱乐系统,基于ARM Cortex-A72平台:

配置项 裁剪前 裁剪后 缩减比例
内核镜像(zImage) 18.2 MB 4.1 MB 77.5%
设备树(DTB) 128 KB 96 KB 25%
内核模块(.ko文件) 12.5 MB 3.2 MB 74.4%
总内核体积 30.8 MB 7.4 MB 76%
启动时间 8.2秒 3.1秒 62.2%

看到没?从30MB瘦到7.4MB,启动时间从8秒降到3秒。这就是裁剪的威力。

注意: 裁剪不是越狠越好。我曾经为了追求极致体积,把内核压缩算法从gzip换成lzma,结果解压时间翻了一倍。启动时间反而变长了。一定要做实际测试,别只看镜像大小。

具体怎么操作?我一般用 make savedefconfig 生成精简配置,然后对比差异:

# 生成当前配置的精简版
make savedefconfig
# 对比原始配置
diff .config defconfig

这样能清楚看到哪些选项被关了。我习惯把裁剪记录写成脚本,下次换内核版本时直接复用。

3.4 避坑指南

最后分享几个我踩过的坑:

  • 别关掉串口驱动:调试全靠它。我有一回关了串口,系统起不来连日志都看不到,只能重新烧录。
  • 文件系统驱动要谨慎:根文件系统用的驱动必须built-in。我见过有人把ext4做成模块,结果内核启动后找不到根分区,直接panic。
  • 网络驱动别乱关:车载虽然不需要Wi-Fi,但以太网和CAN总线驱动是必须的。OTA升级全靠它们。
  • 测试要全面:裁剪后至少跑一轮压力测试。我曾经关掉了一个看起来没用的电源管理驱动,结果系统休眠后唤不醒。
我的习惯: 每次裁剪后,先用qemu模拟运行一遍,确认能正常启动。然后再烧到真机上测试。这样能省下不少反复烧录的时间。