3、内核配置与裁剪:从“臃肿”到“精干”的必修课
说实话,我刚入行做车载Linux那会儿,最头疼的就是内核配置。动不动就几百兆的vmlinux,烧进去连启动都费劲。后来我明白了——内核裁剪不是炫技,是生存技能。车载系统资源就那么点,你多开一个模块,可能就多一次崩溃的风险。
这一章,咱们就聊聊怎么把内核从“大胖子”变成“精干小伙”。
3.1 内核配置选项详解:别被Kconfig吓到
内核的配置系统,说白了就是一套菜单系统。每个驱动、每个功能模块,都对应一个Kconfig文件。你运行make menuconfig,看到的就是这些Kconfig渲染出来的界面。
我习惯把配置选项分成三类:
| 类型 | 符号 | 含义 | 典型场景 |
|---|---|---|---|
| 内置 | y |
编译进内核镜像,常驻内存 | 必须用的驱动(如串口、中断控制器) |
| 模块 | m |
编译成.ko文件,按需加载 | 不常用但偶尔需要的驱动(如USB摄像头) |
| 禁用 | n |
完全不编译 | 硬件上没有的功能(如Wi-Fi模块) |
这里有个坑——别一股脑全选y。我见过有人把内核编到50MB,结果启动时内存直接爆了。车载系统里,y只给那些启动阶段就必须用的东西。其他的,能m就m,能n就n。
make savedefconfig,生成一个最小化的defconfig。这样你改了什么,一目了然。
3.2 裁剪原则:少即是多,但不是乱删
裁剪不是让你瞎删。你得有原则。我总结了四条铁律:
- 硬件决定论:板子上没有的硬件,对应的驱动直接
n。比如你的SoC没有GPU,那DRM、GPU驱动统统关掉。 - 启动路径优先:从uboot到根文件系统挂载,这条路径上的驱动必须
y。其他的,等系统起来了再加载也不迟。 - 功能最小化:车载系统不需要桌面、不需要蓝牙耳机、不需要打印机。这些子系统,能关就关。
- 调试符号剥离:发布版本别带
DEBUG选项,那玩意儿能让内核体积翻倍。
我曾经在一个项目里,把内核从12MB裁到3.2MB。怎么做到的?就是把所有没用过的驱动全关了。你想想看,一个车载信息娱乐系统,要什么CONFIG_NFTABLES?要什么CONFIG_WIRELESS?统统干掉。
CONFIG_EXT4_FS也关了。我见过有人裁完内核,结果根文件系统挂不上——因为文件系统驱动没了。嗯,那场面,相当尴尬。
3.3 最小内核配置实战:手把手教你“瘦身”
好,理论说完了,咱们来点实际的。假设你手里有一块i.MX6ULL的板子,256MB RAM,256MB NAND Flash。目标是跑一个车载仪表盘系统。
3.3.1 第一步:生成基准配置
# 先用默认配置
make imx_v6_v7_defconfig
# 看看有多大
make -j4
ls -lh arch/arm/boot/zImage
# 输出:-rw-r--r-- 1 root root 5.2M ... zImage
5.2MB,还行。但咱们的目标是2MB以内。继续。
3.3.2 第二步:关闭不需要的子系统
进入make menuconfig,按下面这个清单操作:
| 路径 | 选项 | 操作 | 节省空间 |
|---|---|---|---|
| General setup | CONFIG_SWAP | 关(n) | ~50KB |
| Networking support | CONFIG_NET | 如果不需要网络,直接关 | ~500KB |
| Device Drivers → Graphics support | CONFIG_DRM | 保留fbdev,关掉DRM | ~300KB |
| File systems | CONFIG_EXT2_FS, CONFIG_BTRFS_FS等 | 只保留ext4和squashfs | ~200KB |
| Kernel hacking | CONFIG_DEBUG_KERNEL | 全部关掉 | ~1MB |
这一步做完,再编译看看:
make -j4
ls -lh arch/arm/boot/zImage
# 输出:-rw-r--r-- 1 root root 2.8M ... zImage
2.8MB,离目标还差一点。
3.3.3 第三步:驱动级裁剪
这是最费功夫的一步。你得知道板子上到底有哪些硬件。我一般这么干:
- 看原理图,列出所有外设的型号。
- 在menuconfig里搜索对应的驱动,只保留这些。
- 其他的,比如
CONFIG_TOUCHSCREEN、CONFIG_SOUND,如果不用,直接关。
举个例子,i.MX6ULL的LCD控制器是mxsfb,那就只保留这个:
Device Drivers → Graphics support →
[*] Support for frame buffer devices →
[*] MXS LCDIF framebuffer support
# 其他的fb驱动全关
再编译:
make -j4
ls -lh arch/arm/boot/zImage
# 输出:-rw-r--r-- 1 root root 1.9M ... zImage
1.9MB,搞定。
3.4 知识结构图:内核裁剪的核心逻辑
下面这张图,是我自己总结的裁剪决策流程。你照着走,基本不会出错。
你看,整个流程其实不复杂。核心就一句话:用不到的,就别编进去。
3.5 避坑指南:我踩过的那些雷
最后,分享几个我亲身经历过的坑:
- 别信“默认配置”:厂商给的defconfig,往往开了很多你用不到的东西。我遇到过一块板子,默认配置里居然有
CONFIG_WIFI_BCM4334,但板子上根本没有Wi-Fi芯片。 - 小心“依赖链”:你关了一个选项,可能连带关掉其他依赖项。比如关了
CONFIG_INPUT,所有输入设备驱动都没了。嗯,我当时连按键都用不了。 - 启动日志是好朋友:裁剪后第一次启动,一定要开
earlyprintk。如果内核panic了,你能看到最后一条日志,就知道是哪个驱动出了问题。 - 保留一个“安全内核”:我习惯在SD卡里存一份没裁剪的内核。万一裁坏了,还能从SD卡启动救回来。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules -j4,然后对比前后体积。如果体积没怎么变,说明你还没裁到点子上。