4. 内核配置基础:Kconfig 语法入门、配置选项类型与依赖选择关系

Linux 内核的配置系统由 Kconfig 语言驱动,它定义了所有可配置选项的结构、类型、依赖和默认值。理解 Kconfig 是进行内核裁剪和定制的前提。本章将系统讲解 Kconfig 的核心语法、四种基本配置选项类型以及依赖与选择关系的实现机制。

核心认知: Kconfig 不是编程语言,而是一种声明式配置描述语言。它不控制执行流程,只描述“在什么条件下,哪些选项可见、可选、默认为何值”。

4.1 Kconfig 语法基础

Kconfig 文件通常位于内核源码树各子目录的 Kconfig 文件中,通过 source 语句形成层级结构。每个配置条目以关键字开头,后跟配置宏名称和属性块。

4.1.1 基本条目结构

config CPU_FREQ
    bool "CPU Frequency scaling"
    default y
    help
      This option enables the CPU frequency scaling subsystem.
      Say Y here if you want to control CPU performance states.

每个 config 条目定义一个配置宏(如 CONFIG_CPU_FREQ),包含类型、提示字符串、默认值、依赖关系和帮助信息。

4.1.2 常用关键字速查表

关键字 用途 示例
config 定义配置选项 config FOO
bool/tristate/int/string 声明选项类型 tristate "Support for XYZ"
depends on 声明依赖关系 depends on PCI
select 反向选择(强制选中) select LIBFDT
default 设置默认值 default y if ARCH_X86
help 提供帮助文本 help\n This driver ...
source 包含子目录 Kconfig source "drivers/usb/Kconfig"
choice 定义互斥选项组 choice\n prompt "Select algorithm"
if/endif 条件块 if EXPERT\n config DEBUG\nendif
提示: 在 make menuconfig 界面中,按 ? 键可以查看当前选项的完整 Kconfig 定义,包括依赖链和反向选择关系。

4.2 配置选项类型详解

Kconfig 支持四种基本类型,每种类型决定了选项的取值空间和界面表现。

4.2.1 bool(布尔型)

取值为 y(编译进内核)或 n(不编译)。用于开关类功能,如是否启用某个子系统。

config DEBUG_FS
    bool "Debug Filesystem"
    default n
    help
      Enable debugfs, a virtual filesystem for kernel debugging.

4.2.2 tristate(三态型)

取值为 y(编译进内核)、m(编译为可加载模块)或 n(不编译)。这是 Linux 内核模块化设计的核心类型,驱动和文件系统通常使用此类型。

config USB_STORAGE
    tristate "USB Mass Storage support"
    depends on USB && SCSI
    default m
    help
      Say Y here to include USB storage drivers in kernel,
      or M to build as modules.

4.2.3 int(整型)

用于配置数值参数,如缓冲区大小、超时时间、端口号等。可以指定取值范围。

config LOG_BUF_SHIFT
    int "Kernel log buffer size (2^N)"
    range 12 25
    default 18
    help
      Size of the kernel log buffer, as power of 2.

4.2.4 string(字符串型)

用于配置路径、设备名称、版本号等文本信息。

config DEFAULT_HOSTNAME
    string "Default hostname"
    default "(none)"
    help
      Default hostname assigned to the system at boot.

4.2.5 类型对比表

类型 取值空间 界面控件 典型用途 模块支持
bool y / n 复选框 功能开关、子系统启用 否
tristate y / m / n 三态选择框 驱动、文件系统、协议栈 是
int 整数(可设范围) 数字输入框 缓冲区大小、超时值 否
string 任意文本 文本输入框 路径、名称、参数 否
注意: 只有 tristate 类型的选项可以编译为模块(m)。如果一个驱动必须内置(如早期启动需要的驱动),应使用 bool 类型。

4.3 依赖与选择关系

内核配置选项之间存在复杂的逻辑关系,Kconfig 通过 depends on、select 和 choice 三种机制来管理这些关系。

4.3.1 depends on(依赖)

表示当前选项只有在依赖条件满足时才可见和可配置。依赖可以是单个选项,也可以是逻辑表达式。

config SND_HDA_INTEL
    tristate "Intel HD Audio"
    depends on SND && (X86 || PPC)
    help
      Intel HD Audio driver for x86 and PowerPC platforms.

依赖表达式支持 &&(与)、||(或)、!(非)运算符。

4.3.2 select(反向选择)

当当前选项被选中时,select 会强制将另一个选项也设置为 y(或 m)。常用于解决“隐藏依赖”——即用户不需要知道但必须启用的底层选项。

config DEVTMPFS
    bool "Maintain a devtmpfs filesystem"
    default y
    select TMPFS
    help
      This creates a tmpfs-based /dev at early boot.

上例中,只要 DEVTMPFS 被选中,TMPFS 就会被自动强制启用。

4.3.3 choice(互斥选择)

用于定义一组互斥选项,用户只能从中选择一个。常用于调度算法、压缩算法、CPU 厂商选择等场景。

choice
    prompt "Default I/O scheduler"
    default MQ_IOSCHED_DEADLINE

    config MQ_IOSCHED_DEADLINE
        bool "Deadline"
    config MQ_IOSCHED_KYBER
        bool "Kyber"
    config MQ_IOSCHED_BFQ
        bool "BFQ"
endchoice

4.3.4 依赖关系可视化

下面这张 SVG 图展示了一个典型驱动选项的依赖与选择关系网络:

Kconfig 依赖与选择关系示例 CONFIG_USB CONFIG_USB_STORAGE CONFIG_USB_HID CONFIG_USB_SERIAL CONFIG_SCSI CONFIG_HID CONFIG_TTY 图例说明 实线箭头 = depends on(依赖) | 虚线箭头 = select(反向选择)

4.4 条件表达式与 if 块

Kconfig 支持使用 if 块对一组选项施加相同的依赖条件,避免重复书写 depends on。

if EXPERT

config DEBUG_KERNEL
    bool "Kernel debugging"
    default n

config MAGIC_SYSRQ
    bool "Magic SysRq key"
    default n

endif

上述代码等价于为 DEBUG_KERNEL 和 MAGIC_SYSRQ 分别添加 depends on EXPERT。

4.5 默认值策略

Kconfig 的 default 关键字可以附带条件,实现“平台感知”的默认配置。

config NR_CPUS
    int "Maximum number of CPUs"
    range 2 512
    default "64" if X86_64
    default "8" if ARM
    default "4"

当条件不满足时,使用最后的无条件默认值。如果没有任何 default 语句,bool 和 tristate 默认为 n,int 和 string 默认为空。

最佳实践: 在编写 Kconfig 时,始终为 int 和 string 类型提供明确的 default 值,避免配置系统出现未定义行为。

4.6 实战:编写一个简单的 Kconfig 片段

假设我们要为一个嵌入式开发板添加一个自定义 LED 驱动,其 Kconfig 定义如下:

config LED_CUSTOM
    tristate "Custom board LED driver"
    depends on GPIOLIB && LEDS_CLASS
    select GPIO_SYSFS
    default y if BOARD_MY_EMBEDDED
    default m
    help
      This driver controls the user LEDs on MyEmbedded board.
      Say Y to compile into kernel, M for module, N to disable.

if LED_CUSTOM

config LED_CUSTOM_BLINK
    bool "Support software blinking"
    default y
    help
      Enable software-based blinking without hardware timer.

config LED_CUSTOM_MAX_BRIGHTNESS
    int "Maximum brightness value"
    range 0 255
    default 128
    help
      Maximum brightness level for the custom LED.

endif

这个例子综合运用了 tristate、bool、int、depends on、select、条件默认值和 if 块,覆盖了本章所有核心知识点。

4.7 本章小结

  • Kconfig 是内核配置的声明式语言,通过 config 条目定义每个选项。
  • 四种基本类型 bool、tristate、int、string 分别对应开关、三态、数值和文本配置。
  • depends on 控制选项的可见性,select 强制启用隐藏依赖,choice 实现互斥选择。
  • 条件表达式和 if 块可以批量管理依赖,default 支持平台感知的默认值策略。
  • 掌握 Kconfig 语法是进行内核裁剪、驱动移植和嵌入式系统定制的基础能力。