4、内核配置系统详解:从界面到底层逻辑
内核配置,说白了就是告诉 Linux 内核:「你要支持哪些硬件?要开启哪些功能?」。这一步没做好,后面编译出来的内核要么跑不起来,要么臃肿得像头大象。我刚开始做嵌入式时,就吃过这个亏——编译了个全功能内核,结果 8MB 的 Flash 根本放不下。
这一章,我们就把内核配置系统彻底讲透。从交互界面到配置文件结构,再到裁剪原则,一条线串下来。
4.1 四种配置界面:你该用哪个?
Linux 内核提供了四种配置工具,各有各的适用场景。我列个表,你一看就明白。
| 命令 | 界面类型 | 适用场景 | 依赖 |
|---|---|---|---|
make config |
命令行问答 | 脚本自动化、极简环境 | 无 |
make menuconfig |
文本菜单 (ncurses) | 嵌入式开发最常用 | libncurses-dev |
make xconfig |
图形界面 (Qt) | 桌面开发、新手友好 | qt5-dev-tools |
make gconfig |
图形界面 (GTK+) | GNOME 环境用户 | libgtk-3-dev |
我个人习惯用 make menuconfig。为什么?因为它不依赖图形桌面,在 SSH 终端里就能跑,而且操作效率极高。你想想看,嵌入式开发经常要连开发板、连服务器,哪有那么多图形界面给你用?
/ 键可以搜索配置项。比如你想找 USB 相关的选项,直接按 / 输入 USB,所有匹配项就列出来了。这个功能我几乎每天都在用。
4.2 配置选项的依赖关系:别乱勾
内核配置项不是独立的。它们之间有复杂的依赖关系。你勾了一个选项,可能自动带出来一堆依赖项;你取消一个选项,也可能导致其他选项变灰。
这种依赖关系在 Kconfig 文件中定义。每个配置项都有三种基本属性:
- bool:要么编译进内核 (Y),要么不编译 (N)。
- tristate:三种状态——编译进内核 (Y)、编译成模块 (M)、不编译 (N)。
- depends on:依赖条件。只有依赖项满足时,当前选项才可见。
- select:反向依赖。选中当前项时,自动选中依赖项。
举个例子,你打开 CONFIG_USB_SUPPORT 后,CONFIG_USB_EHCI_HCD 才会出现。这就是 depends on 在起作用。
CONFIG_FW_LOADER 取消了。结果网卡驱动死活加载不了固件,系统启动时一直报 firmware 加载失败。查了半天才发现,网卡驱动依赖这个选项。所以,不要随意取消你不认识的选项,尤其是那些被 select 反向依赖的。
4.3 .config 文件结构:内核配置的「源代码」
所有配置最终都保存在内核源码根目录下的 .config 文件中。这个文件是纯文本格式,每一行就是一个配置项。
# 注释行,说明配置项的作用
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSVIPC=y
# 模块配置,=m 表示编译成模块
CONFIG_USB=m
CONFIG_USB_EHCI_HCD=m
# 未配置的选项,前面加 # 注释
# CONFIG_USB_OTG is not set
# 字符串和整数配置
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_LOG_BUF_SHIFT=17
结构其实很简单:
=y:编译进内核=m:编译成模块# ... is not set:不编译="value":字符串或数值参数
你完全可以手动编辑这个文件。但我建议你只在特殊情况下这么做——比如批量修改几个选项时。平时还是用 menuconfig,因为它会自动处理依赖关系。
make olddefconfig 来同步依赖关系。这个命令会自动补全缺失的选项,并设置合理的默认值。我每次手动改完 .config,第一件事就是跑这个命令。
4.4 内核配置裁剪原则:少即是多
嵌入式设备资源有限。Flash 可能只有 4MB、8MB,RAM 可能只有 64MB。内核必须「量体裁衣」。下面这张图展示了裁剪的核心逻辑:
裁剪不是盲目删东西。我总结了一个「三步走」原则:
- 先跑起来,再瘦身:第一次配置时,先用默认配置编译一个能启动的内核。确保硬件能跑通,再开始裁剪。
- 按需裁剪,逐项确认:每关掉一个功能,都要问自己:「这个功能我的设备真的不需要吗?」。比如你的设备只用以太网,那把 WiFi、蓝牙、CAN 总线都关掉。
- 模块化,不固化:驱动尽量编译成模块 (
=m)。这样内核镜像小,运行时按需加载。我见过有人把所有驱动都编进内核,结果镜像 5MB,Flash 都放不下。
- 关闭
CONFIG_DEBUG_KERNEL及其子选项(生产环境不需要内核调试) - 关闭
CONFIG_PRINTK或降低日志缓冲区大小(节省内存) - 关闭不用的文件系统(如 XFS、Btrfs、NTFS)
- 关闭不用的网络协议(如 IPv6、DECnet、IPX)
- 关闭不用的驱动(如显卡、声卡、TV 调谐器)
make savedefconfig 生成一个最小化的 defconfig 文件。这个文件只包含你修改过的选项,干净利落。下次编译时,直接 make defconfig 就能恢复你的配置。我每个项目都会保留一份这样的 defconfig,方便复用。
嗯,内核配置系统就讲到这里。记住:配置不是一次性的工作。随着硬件迭代、需求变化,你随时可能回来调整。掌握这些工具和原则,你就能游刃有余地应对各种场景。