内核配置基础:Kconfig、menuconfig 与模块化思维

做嵌入式 Linux 驱动开发,绕不开内核配置。说白了,这就是告诉内核:「你要支持哪些硬件?哪些功能要编译进去?哪些先放一边?」

我刚开始接触 Tina Linux 时,面对密密麻麻的配置项也懵过。后来发现,只要搞懂 Kconfig 语法、会用 menuconfig,再分清「内建」和「模块」的区别,这事就顺了。

Kconfig 语法:内核配置的「骨架」

Kconfig 不是代码,是描述配置选项的脚本语言。每个驱动目录下都有个 Kconfig 文件,它定义了哪些选项可见、依赖什么、是布尔还是三态。

看个最简单的例子:

config MY_DRIVER
    bool "My custom driver support"
    default y
    help
      Say Y here to enable my custom driver.

这里 bool 表示只有 Y/N 两种选择。如果是 tristate,就有 Y/N/M 三种——M 就是模块。

我个人习惯把 depends on 写在最前面,这样一眼就能看出依赖关系:

config MY_SENSOR
    tristate "My sensor driver"
    depends on I2C
    select REGMAP_I2C
    help
      Enable support for My sensor over I2C.

depends on 是「依赖」,条件不满足时选项不可见。select 是「反向选择」,选中它会自动把另一个选项也选上。我在项目中遇到过因为 select 用错导致编译冲突的情况,后来就尽量用 depends on 了。

小技巧: 写 Kconfig 时,default 值别乱设。驱动默认 n 最安全,除非是板级必选功能。

menuconfig 图形化配置:别被界面吓到

在终端敲 make menuconfig,会弹出一个蓝底菜单。很多人第一次看到觉得复古,但用熟了会发现它比手写 .config 高效得多。

基本操作就几个键:

  • 方向键:上下移动光标
  • Enter:进入子菜单
  • Y:编译进内核(内建)
  • M:编译成模块
  • N:不编译
  • ?:查看帮助
  • /:搜索选项(这个最常用)

为什么搜索重要?因为内核有上万配置项,手动翻菜单会疯掉。按 / 输入关键词,直接定位到目标选项,按 1 就能跳转过去。

注意: 修改配置后一定要保存退出。我见过有人改了半小时,直接关终端,结果白干了。

内建 vs 模块:选 Y 还是选 M?

这是新手最容易纠结的地方。我直接给结论:

特性 内建(Y) 模块(M)
编译方式 直接编入 zImage 生成 .ko 文件
加载时机 内核启动时自动加载 手动 insmod 或自动加载
体积影响 增加内核镜像大小 不增加内核镜像
调试便利性 需重新编译内核 可单独编译模块
适用场景 根文件系统必需的驱动 可热插拔、非必需驱动

我的经验是:启动必须的驱动选 Y,比如存储、串口、网卡。其他都选 M。为什么?因为调试时改一行代码,编译一个 .ko 几秒钟,重新编内核要几分钟。你想想看,哪个效率高?

曾经我为了省事把所有驱动都编成 Y,结果内核镜像大了 30%,启动还慢。后来老老实实按需配置,该 M 就 M。

Tina Linux 内核配置入口:kernel_menuconfig

在 Tina Linux 里,配置内核不是直接敲 make menuconfig,而是用封装好的命令:

source build/envsetup.sh
lunch  # 选择你的方案
make kernel_menuconfig

这条命令会进入内核的 menuconfig 界面。注意,它操作的是 kernel/linux-xxx 目录下的 Kconfig 树,配置结果会保存到 target/allwinner/<board>/config-4.9 之类的路径下。

我建议第一次跑时先看看默认配置:

make kernel_oldconfig

它会基于当前 defconfig 询问新增选项,省得你从头一项项选。

核心流程: 修改 Kconfig → 运行 kernel_menuconfig → 保存 .config → 编译内核 → 验证功能。

知识体系图:内核配置的完整链路

下面这张图帮你理清 Kconfig、menuconfig、.config 和编译之间的关系:

内核配置完整链路 Kconfig 文件 定义选项与依赖 menuconfig 图形化交互配置 .config 最终配置结果 make 编译内核/模块 zImage / .ko 内建 / 模块 Y → 编入 zImage M → 生成 .ko 文件 N → 不编译

避坑指南:我踩过的几个坑

  • 配置没保存就编译:编译的还是旧配置。每次改完记得 make savedefconfig 或直接保存 .config。
  • 模块依赖没选全:选了 M 但它的依赖是 Y,编译报错。用 make menuconfig 的依赖检查功能。
  • Kconfig 语法错误:缩进不对、引号不匹配,menuconfig 直接崩溃。用 scripts/kconfig/conf --help 检查。
  • Tina 多方案配置混淆:不同方案的 defconfig 不同,切换方案后一定要重新 make kernel_menuconfig。
我的习惯: 每次改完配置,先 make kernel_oldconfig 确认没有遗漏,再 make kernel_menuconfig 微调。这样既快又稳。

嗯,内核配置这块,说白了就是「选什么、怎么选、选完怎么办」。Kconfig 是规则,menuconfig 是工具,内建和模块是策略。搞懂这三样,Tina Linux 的驱动配置你就入门了。