第4章:Linux内核配置与裁剪

内核配置与裁剪,说白了就是给A133的Linux内核做「瘦身」。

我刚开始做BSP时,总觉得内核越大越好,驱动越多越安全。结果呢?编译一次半小时,启动要十几秒,还动不动就OOM。后来被老大骂了一顿,才老老实实去研究Kconfig机制。

这一章,我就带你走一遍完整的裁剪流程。从Kconfig原理到menuconfig实战,再到驱动添加,一步不落。

4.1 Kconfig机制:内核配置的「骨架」

Kconfig是什么?它是内核的配置描述语言。每个驱动、每个功能模块,都有一个Kconfig文件来描述它。

举个例子,你想知道某个驱动能不能被编译进内核,就看它的Kconfig怎么写。

# drivers/i2c/busses/Kconfig 中的一段
config I2C_SUNXI
    tristate "Allwinner I2C controller"
    depends on ARCH_SUNXI
    help
      Say Y here to include support for Allwinner I2C controller.
      This driver can also be built as a module.

这里有几个关键点:

  • tristate:三态选择——Y(编译进内核)、M(编译为模块)、N(不编译)
  • depends on:依赖关系,只有ARCH_SUNXI被选中,这个选项才会出现
  • help:帮助信息,告诉你这个驱动是干嘛的
我的小技巧:裁剪时,先看depends on。如果某个驱动依赖的选项你都没选,那它根本不会出现在menuconfig里。省心。

4.2 menuconfig实战:动手裁剪A133内核

好,理论说完了,咱们直接上手。

进入内核源码目录,执行:

cd kernel/
make ARCH=arm64 menuconfig

你会看到一个蓝底白字的界面。别慌,我带你一步步来。

4.2.1 裁剪CPU子系统

A133用的是Cortex-A53,但内核默认支持很多CPU架构。我们只保留ARM64相关的。

General setup  --->
    [*] Support for 64-bit ARM systems
    [ ] Support for 32-bit ARM systems  # 关掉,A133是64位

嗯,这里要注意:如果你关掉了32位支持,有些老驱动可能编译不过。我遇到过这种情况,后来发现是某个传感器驱动用了32位汇编。解决办法是把它也裁剪掉。

4.2.2 裁剪文件系统支持

A133主要用ext4和FAT32。其他文件系统,比如XFS、Btrfs、NTFS,统统关掉。

File systems  --->
    <*> The Extended 4 (ext4) filesystem
    < > The Extended 3 (ext3) filesystem  # 不需要
    < > Btrfs filesystem                  # 不需要
    < > XFS filesystem                    # 不需要
    DOS/FAT/NT Filesystems  --->
        <*> VFAT (Windows-95) fs support
        < > NTFS file system support      # 不需要
效果:光这一步,内核大小就能减少约2MB。启动速度提升约0.5秒。

4.2.3 裁剪网络协议栈

A133是嵌入式设备,不需要完整的TCP/IP协议栈。IPv6、IPsec、多播路由,这些都可以关掉。

Networking support  --->
    Networking options  --->
        [ ] IPv6 support                  # 关掉
        [ ] IP: IPsec transport mode      # 关掉
        [ ] IP: multicast routing         # 关掉

我做过一个项目,客户要求设备只做数据采集,不需要IPv6。关掉后,内核小了800KB,内存占用也降了。

4.3 添加必要的驱动支持

裁剪不是一味地删。有些驱动必须加,否则板子跑不起来。

4.3.1 必须保留的驱动

驱动类别 具体选项 说明
串口驱动 CONFIG_SERIAL_SUNXI 调试输出全靠它
MMC/SD卡驱动 CONFIG_MMC_SUNXI 启动系统用
USB驱动 CONFIG_USB_SUNXI 外接设备用
显示驱动 CONFIG_DRM_SUNXI 屏幕显示用

4.3.2 按需添加的驱动

比如你的产品需要Wi-Fi模块,那就加上:

Device Drivers  --->
    Network device support  --->
        Wireless LAN  --->
            [*] Realtek 8723ds support

我曾经踩过一个坑:加了Wi-Fi驱动,但忘了加固件文件。结果系统启动后,Wi-Fi设备能识别,但连不上网。折腾了两天才发现是固件没放对位置。

注意:添加驱动后,记得检查对应的固件文件是否在/lib/firmware/目录下。否则驱动加载会失败。

4.4 裁剪后的验证与优化

裁剪完,别急着烧录。先做两件事:

  1. 编译验证:make -j8,确保没有编译错误
  2. 启动测试:烧录到板子上,看启动日志,确认没有驱动加载失败

我习惯用这个命令查看内核大小:

ls -lh arch/arm64/boot/Image
# 裁剪前:约 12MB
# 裁剪后:约 6.5MB

启动速度呢?用dmesg看时间戳:

dmesg | grep "Kernel"
# 裁剪前:3.2秒
# 裁剪后:1.8秒
我的经验:裁剪不是一次完成的。我通常会做三轮:第一轮删掉明显不需要的,第二轮根据启动日志删掉报错的驱动,第三轮再精调。三轮下来,内核大小能减少40%-50%。

4.5 避坑指南

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

  • 别删掉initramfs:有一次我为了省空间,把initramfs支持关了。结果系统启动到一半就卡住了。因为根文件系统挂载需要它。
  • 注意驱动依赖链:你关掉一个驱动,可能连带关掉它依赖的驱动。比如关掉I2C,所有I2C设备(触摸屏、传感器)都会失效。
  • 保留调试选项:产品发布前,建议保留CONFIG_DEBUG_KERNEL。出问题时,它能帮你快速定位。

嗯,这一章的内容就到这里。内核裁剪是个细活,急不来。你按我说的步骤走,多试几次,就能找到最适合你产品的配置。

下一章,我们会聊设备树配置。到时候见。