2. Kconfig 语法基础:关键字、数据类型、表达式、注释规则
Kconfig 是 Linux 内核配置系统的领域特定语言,用于定义配置选项的层次结构、依赖关系和默认值。掌握 Kconfig 语法是定制内核功能菜单、裁剪驱动、添加自定义模块的必备技能。本节从关键字、数据类型、表达式和注释四个维度系统讲解 Kconfig 语法基础。
核心认知:Kconfig 文件不是 C 语言,也不是 Makefile,而是一种声明式配置描述语言。每个配置选项最终会生成一个
CONFIG_XXX 宏,供 C 源码和 Makefile 使用。
2.1 关键字体系
Kconfig 关键字分为三类:配置定义关键字、菜单结构关键字、属性关键字。下表列出最常用的 12 个关键字及其用途。
| 分类 | 关键字 | 用途说明 |
|---|---|---|
| 配置定义 | config |
定义一个配置选项,后跟选项名(如 CONFIG_FOO) |
menuconfig |
定义带子选项的配置菜单项,可展开/折叠 | |
choice / endchoice |
定义单选组,组内只能选中一个选项 | |
comment |
在配置界面中显示一段只读注释文本 | |
| 菜单结构 | menu / endmenu |
定义一个可折叠的菜单分组 |
if / endif |
条件块,内部选项仅在条件为真时可见 | |
source |
引入另一个 Kconfig 文件,支持路径通配 | |
| 属性 | bool / tristate |
布尔型(y/n)或三态型(y/m/n) |
int / hex / string |
整数、十六进制、字符串类型 | |
default |
设置默认值,可被依赖条件覆盖 | |
depends on |
声明依赖关系,依赖不满足时选项不可见 | |
select / imply |
反向依赖:选中当前项时自动选中/推荐另一项 |
实战提示:
menuconfig 与 config 的区别在于前者在配置界面中自带一个子菜单展开箭头,适合作为功能模块的根开关;后者是普通单选项。
2.2 数据类型与值域
Kconfig 支持 5 种数据类型,每种类型对应不同的值域和界面控件。理解数据类型是正确设计配置选项的前提。
| 类型 | 关键字 | 值域 | 界面控件 | 典型用途 |
|---|---|---|---|---|
| 布尔 | bool |
y / n |
复选框 | 功能开关、驱动启用 |
| 三态 | tristate |
y / m / n |
三选一单选按钮 | 可编译为模块的驱动 |
| 整数 | int |
整数范围(可设 range) |
数字输入框 | 缓冲区大小、超时值 |
| 十六进制 | hex |
十六进制数(可设 range) |
十六进制输入框 | 内存地址、硬件寄存器 |
| 字符串 | string |
任意文本 | 文本输入框 | 设备路径、固件文件名 |
# 数据类型示例
config MY_FEATURE
bool "Enable My Feature" # 布尔:y/n
config MY_DRIVER
tristate "My Driver Support" # 三态:y/m/n
config MY_BUFFER_SIZE
int "Buffer Size (bytes)"
range 64 4096
default 256
config MY_BASE_ADDR
hex "Base Address"
range 0x1000 0xF000
default 0x2000
config MY_PATH
string "Device Path"
default "/dev/mydev"
常见错误:三态类型
tristate 的选项如果被 depends on 依赖的选项为 n,则该选项自动变为 n,即使手动设为 y 或 m 也会被强制覆盖。这是初学者最容易踩的坑。
2.3 表达式与依赖逻辑
Kconfig 表达式用于描述配置选项之间的依赖、默认值条件和可见性控制。表达式由操作符和操作数组成,操作数可以是配置符号、常量 y/m/n 或子表达式。
2.3.1 操作符优先级
| 优先级 | 操作符 | 含义 | 示例 |
|---|---|---|---|
| 1(最高) | ! |
逻辑非 | !CONFIG_A |
| 2 | && |
逻辑与 | A && B |
| 3 | || |
逻辑或 | A || B |
| 4(最低) | = / != |
等于 / 不等于 | A = y、A != n |
2.3.2 表达式使用场景
- depends on:选项可见性依赖。
depends on A && B表示 A 和 B 都必须为真。 - default:条件默认值。
default y if A表示当 A 为真时默认 y。 - select / imply:反向依赖的条件。
select C if D表示选中当前项且 D 为真时自动选中 C。 - if / endif:块级条件,内部所有选项受条件约束。
# 表达式综合示例
config A
bool "Option A"
config B
bool "Option B"
depends on A # 仅当 A=y 时可见
config C
tristate "Option C"
default y if A && B # A 和 B 都选中时默认 y
default m if A || B # 否则只要 A 或 B 选中就默认 m
default n # 其他情况默认 n
config D
bool "Option D"
select E if C = y # 当 C=y 时自动选中 E
if A
config F
bool "Option F" # 整个块仅在 A=y 时可见
endif
表达式求值规则:Kconfig 使用三值逻辑(y/m/n)。
y 为真,m 在 depends on 中视为真但在 if 条件中视为假,n 为假。这是三态类型特有的微妙之处。
2.4 注释规则
Kconfig 支持两种注释方式,用于提高文件可读性和维护性。
| 注释方式 | 语法 | 特点 | 示例 |
|---|---|---|---|
| 行注释 | # 开头 |
单行,可出现在行首或行尾 | # This is a comment |
| 界面注释 | comment "文本" |
在配置界面中显示为只读文本,可带 depends on |
comment "Advanced options" depends on EXPERT |
# ============================================
# 行注释示例:用于文件头、段落分隔、代码说明
# ============================================
# 以下配置用于 USB 音频设备
config USB_AUDIO
tristate "USB Audio support"
depends on USB && SOUND
help
Say Y here to enable USB audio devices.
If unsure, say N.
# 界面注释:在配置菜单中显示分隔说明
comment "USB Audio drivers are experimental"
depends on EXPERT
最佳实践:
- 使用
#注释解释复杂表达式的意图,如# 仅当 DMA 和中断都启用时可见。 - 使用
comment在配置界面中分组提示,配合depends on控制显示条件。 - Kconfig 不支持块注释(如
/* */),多行注释需每行加#。
2.5 完整语法示例:一个迷你配置菜单
综合以上知识点,下面是一个完整的 Kconfig 文件示例,展示关键字、数据类型、表达式和注释的协同使用。
#
# drivers/misc/my_device/Kconfig
# My Device 驱动配置菜单
#
menu "My Device Support"
config MY_DEVICE_ENABLE
bool "Enable My Device"
default y
help
Master switch for My Device driver.
if MY_DEVICE_ENABLE
config MY_DEVICE_MODE
int "Operation Mode (0-3)"
range 0 3
default 1
help
0: Polling mode
1: Interrupt mode
2: DMA mode
3: Hybrid mode
config MY_DEVICE_IRQ
int "IRQ Number"
default 16
depends on MY_DEVICE_MODE != 0
help
IRQ line used when not in polling mode.
config MY_DEVICE_DMA
bool "DMA Support"
depends on MY_DEVICE_MODE = 2 || MY_DEVICE_MODE = 3
select DMA_ENGINE
help
Enable DMA transfers for mode 2 and 3.
config MY_DEVICE_DEBUG
bool "Debug Output"
default n
endif # MY_DEVICE_ENABLE
comment "My Device requires kernel 5.10+"
depends on MY_DEVICE_ENABLE
endmenu
关键点回顾:
menu/endmenu定义菜单分组,if/endif控制可见性。depends on用于选项级依赖,select用于反向自动选中。range限制int和hex的合法值域。help块提供详细说明,在配置界面中按?键查看。comment在界面中显示只读提示,适合放置版本要求或警告信息。