内核配置基础:从 defconfig 到 menuconfig

内核配置,说白了就是告诉编译器:哪些功能要编译进内核,哪些编译成模块,哪些干脆不要。我刚开始接触 Rockchip 平台时,觉得这步就是跑个 make menuconfig 完事。后来才发现,配置不对,轻则功能缺失,重则系统都起不来。

这一章,我们就把内核配置的底牌翻出来看看。

4.1 三板斧:defconfig、menuconfig、.config

Rockchip 平台的内核配置,核心就三个东西:

  • 默认配置(defconfig):芯片厂商提供的“标准答案”
  • 图形化配置(menuconfig):你手动调整的交互界面
  • .config 文件:最终生效的配置文件

三者的关系,我画了张图,你看一眼就明白了。

Rockchip 内核配置流程 rockchip_linux_defconfig 厂商提供的默认配置 make menuconfig 图形化交互调整 .config 最终生效配置 关键说明: • defconfig 是起点,menuconfig 是调整手段,.config 是终点 • 每次 make menuconfig 保存后,都会覆盖 .config • 不要直接手动编辑 .config,除非你清楚自己在做什么 • 保存 .config 前,建议备份一份 defconfig 原始文件

4.2 第一步:加载默认配置

拿到 Rockchip 的内核源码后,第一件事就是加载芯片对应的默认配置。以 RK3588 为例:

make ARCH=arm64 rockchip_linux_defconfig

这条命令干了什么?它把 arch/arm64/configs/rockchip_linux_defconfig 文件复制到源码根目录,重命名为 .config。

我的习惯:每次执行 defconfig 前,我都会先看一眼 arch/arm64/configs/ 目录下有哪些文件。Rockchip 平台通常有多个 defconfig,比如 rockchip_linux_defconfig 是通用版,rockchip_linux_defconfig_debug 是调试版。选错了,后面全是坑。

4.3 第二步:图形化微调

默认配置能满足大部分场景,但总有些功能需要你手动开关。这时候就该 menuconfig 上场了。

make ARCH=arm64 menuconfig

界面出来后,你会看到按功能分类的菜单树。我常用的操作就三个:

  • 搜索:按 / 键,输入关键词,快速定位配置项
  • 切换状态:按 Y 编译进内核,按 M 编译成模块,按 N 禁用
  • 保存退出:按左右箭头选 Save,再选 Exit

我曾经踩过的坑:有次我改了配置后直接按 Exit,没点 Save。结果编译出来的内核跟之前一模一样,排查了半天才发现配置根本没保存。记住:Exit 不保存,Save 才保存。

4.4 .config 文件结构

打开 .config 文件,你会看到成百上千行配置项。结构其实很简单:

# 注释行,以 # 开头
# CONFIG_XXX is not set

# 配置项被启用(编译进内核)
CONFIG_ROCKCHIP_I2S=y

# 配置项被编译成模块
CONFIG_ROCKCHIP_CRYPTO=m

# 配置项带参数
CONFIG_ROCKCHIP_GRF_BASE=0xFE000000

每个配置项的值有三种可能:

值 含义 说明
y 编译进内核 功能直接集成到内核镜像中,启动时可用
m 编译成模块 生成 .ko 文件,需要时手动加载
n 或未设置 禁用 该功能完全不编译

我的建议:驱动开发阶段,尽量把相关驱动设为 y。设为 m 虽然灵活,但模块加载顺序、依赖关系处理起来很麻烦。等产品稳定了,再考虑把不常用的驱动改成模块。

4.5 配置依赖:你动一个,可能牵出一串

内核配置项之间是有依赖关系的。比如你想启用某个 Rockchip 的音频驱动,它可能依赖 I2C 控制器、DMA 引擎、时钟框架等。如果你只选了音频驱动,没选依赖项,menuconfig 会自动帮你选上,或者直接灰掉让你选不了。

这种依赖关系定义在 Kconfig 文件中。举个例子:

config ROCKCHIP_I2S
    tristate "Rockchip I2S controller"
    depends on ARCH_ROCKCHIP
    select SND_SOC_GENERIC_DMAENGINE_PCM
    help
      Say Y here to include support for Rockchip I2S controller.

这里 depends on 表示前置条件,select 表示自动选中。我刚开始看这些时,总觉得 depends on 和 select 差不多。后来才搞明白:depends on 是“你必须有”,select 是“我帮你选上”。

4.6 保存与备份:别让配置丢了

配置调好后,我建议你做两件事:

  1. 保存一份到 defconfig:make ARCH=arm64 savedefconfig,这条命令会生成一个精简版的 defconfig,只包含你修改过的配置项。
  2. 备份 .config:cp .config config_$(date +%Y%m%d),万一改坏了还能回滚。

我的工作流:每次调完配置,我都会用 diff .config arch/arm64/configs/rockchip_linux_defconfig 看看改了哪些地方。这样心里有数,也方便写提交说明。

4.7 常见问题与避坑

  • 配置冲突:两个配置项互斥时,menuconfig 会提示。别硬来,看看依赖关系再决定。
  • 配置丢失:执行 make distclean 会删除 .config,记得备份。
  • 配置不生效:改了 .config 后一定要重新编译,make 不会自动检测配置变化。

嗯,内核配置这块,说难不难,说简单也不简单。关键是理解 defconfig、menuconfig、.config 这三者的关系,以及配置项之间的依赖。掌握了这些,后面编译内核、调试驱动,才能顺风顺水。