menuconfig和、Kconfig介绍及例子解析!
来源:嵌入式大杂烩发布时间:2022-04-102122浏览
询问 AI1. menuconfig 和Kconfig 介绍
有过 linux 内核开发经验的人,对menuconfig 不会陌生。对于各类内核,只要是支持menuconfig 配置界面,都是使用Kconfig。
换言之:
- menuconfig:支持配置内核的图形化界面。
- Kconfig:生成menuconfig 界面的脚本语言。
故我们只要熟悉了Kconfig 的语法规则,就熟悉了 menuconfig的应用。这样对于基于menconfig 配置界面的各类内核都能得心应手了。
2. 配置界面
linux 内核的配置界面如下:

思考两个问题:
- 这个配置文件是如何组织和生成的?
- 各项配置又是如何被使用的?
2.1 界面生成和组织
熟悉内核的都知道, 配置内核的过程中只需要执行 make menconfig 界面就自动出来了。
那么,在执行make mneconfig 的过程中到底发生了什么?
Makefile
scripts/kconfig/Makefile
- 顶层Makefile:依赖子makefile。这里MAKECMDGOALS 变量很重要。

- scripts/kconfig/Makefile。顶层makefile 执行


make menuconfig 过程:
- 首先执行顶层Makefile。
- 然后执行scripts/kconfig/Makefile
- 编译 kconfig 下相关工具。
- 生成mconf 工具
lxdialog:checklist/inputbox/menubox/texbox/yesno等图形显示组件mconf:menuconfig 读写解析应用
menu:菜单处理
conf:xxxdefconfig 解析

mconf 核心代码如下:
//script/kconfig/mconf.c
int main(int ac, char **av)
{
char *mode;
int res;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
signal(SIGINT, sig_handler);
conf_parse(av[1]);
conf_read(NULL);
mode = getenv("MENUCONFIG_MODE");
if (mode) {
if (!strcasecmp(mode, "single_menu"))
single_menu_mode = 1;
}
if (init_dialog(NULL)) {
fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
return 1;
}
set_config_filename(conf_get_configname());
conf_set_message_callback(conf_message_callback);
do {
conf(&rootmenu, NULL);
res = handle_exit();
} while (res == KEY_ESC);
return res;
}
我们可以看到,干了三件事:
- 解析Kconfig:./mconf Kconfig
- 生成对话框:init_dialog
- 配置界面:conf
最终会将配置界面设置保存成 .config 文件。
2.2 .config 应用
我们在编译内核前通过有两种操作:
- make xxx_defconfig;make uImage;
- make xxx_defconfig; make menucnfig; make uImage;
make xxx_defconfig 操作会生成 conf 应用,并且解析xxx_defconfig。make menuconfig 操作会生成 mconf 应用,会将我们配置的选项保存成 .config
当我们在执行编译内核的时候,会自动将 .config 里面的配置 转换成相应的宏到 autoconf.h 里面。
2.2.1 .config 保存
//mconf
// 对话框退出
main()
handle_exit()
conf_write() //script/kconf/confdata.c
conf_message(_("configuration written to %s"), newname)
// 配置后保存
main()
conf()
conf_save()
conf_write() //script/kconf/confdata.c
conf_message(_("configuration written to %s"), newname)
// conf : conf 直接将xxx_defconfig 保存成 .config
main()
conf_write()
无论是是 menuconfg 配置, 还是解析 xxx_defconfig 最终都会先保存成 .config
2.2.2 .config 解析
当我们配置生成好 .config 后。在编译内核的时候,会提前将 .config 转换对应的宏。
//conf.c
main();
conf_write_autoconf();
file_write_dep("include/config/auto.conf.cmd");
....
if (!name)
name = "include/generated/autoconf.h";
if (rename(".tmpconfig.h", name))
return 1;
name = getenv("KCONFIG_TRISTATE");
if (!name)
name = "include/config/tristate.conf";
if (rename(".tmpconfig_tristate", name))
return 1;
name = conf_get_autoconfig_name();
2.2.3 总结
linux 内核主要是基于 Kconfig 来组织menuconfig从而达到配置内核的目的。那么主要从两方面入手。
- make menuconfig :生成mconf 应用,产生图形界面,并且保存.config
- make xxx_defconf:生成conf 应用,解析xxx_defconf,并保存成.config
本质上.config 和 xxx_defconfig 是同一文件。
在编译内核的过程中会将 .config 转换为相应的宏,包含在头文件autoconf.h 中,这样就可以供内核使用了。
故我们只需要掌握了 Kconfig 配置,就基本掌握了menuconfig 配置和添加流程。
3. Kconfig 常用语法
3.1 配置项前缀
在Kconfig文件中,假设配置项的名字是XXX,在.config文件中:
- 默认情况下,它对应的变量名为CONFIG_XXX
- 如果设置了环境变量CONFIG_=ABC,则对应的变量名为ABC_XXX
3.2 单个配置项 config

如图 USB Webcam Gadget 就是一个配置项:
- 输入M:编成模块形式。.config 对应 CONFIG_USB_G_WEBCAM=M
- 输入N:不选择配置。.config 对应 CONFIG_USB_G_WEBCAM is not set
3.2.1. 语法
我们还是以一个例子说明:
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC
help
The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests and stream video data to the host. Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_webcam".
config 配置基础语法如下:
config option
type "xxx" //简单描述
depends on xxx //依赖选项,可选
default xxx //初始值
help //帮助信息
xxxxxxxxxxxxxxx
- config option 是一个配置的开始,紧跟着的是配置选项的名称。
- config 下定义了以下属性:
- 类型、输入提示、依赖关系、默认值、帮助信息。
- 每个表示配置的菜单都有类型。变量共有五种类型。
- bool:布尔类型
- tristate:三态类型
- string:字符串
- hex:十六进制
- int:整型
- "USB Webcam Gadget":提示信息
- depends on:表示依赖关系。只有VIDEO_DEV 选中,才可以选择该项
- default:表示配置项的默认值。bool 类型可以是 y/n
- help:帮助信息
3.2.2. 示例
config TEST_A
bool "config test A"
default y
help
test config test A, yes/no
config TEST_B
bool "config test B"
depends on TEST_A
default y
help
test config test B, yes/no
TEST_B 只有在A 选中才能生效。

3.3. 菜单menu/endmenu

如图 USB audio choice 包含两个配置项。UAC1_PLAY 和 UAC1_CAP
3.3.1. 语法
menu "USB audio choice"
depends on GADGET_UAC1
config GADGET_UAC1_PLAY
tristate "USB audio play"
default y
config GADGET_UAC1_CAP
default y
tristate "USB audio cap"
choice
prompt "cap from"
default MIC
depends on GADGET_UAC1_CAP
config GADGET_UAC1_CAP_USER
bool "cap from user"
config GADGET_UAC1_CAP_MIC
bool "cap from mic"
endchoice
endmenu
我们先忽略 choice 和 endchoice。menu 语法以 menu 开始,endmenu 结束。中间包含若干项config配置, 当然也可以包含 其他语法。
3.3.2. 示例
menu "test menu"
config TEST_MENU_A
tristate "menu test A"
config TEST_MENU_B
bool "menu test B"
default n
endmenu
test menu 包含两个配置项:

3.4. 单选 choice/endchoice

如图为 linux usb gadget 驱动,支持各种gadget 设备:
3.4.1 语法
choice
config USB_G_HID
tristate "HID Gadget"
select USB_LIBCOMPOSITE
help
¦ The HID gadget driver provides generic emulation of USB
¦ Human Inter
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
......
config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC
help
¦ The Webcam Gadget acts as a composite USB Audio and Video Class
¦ device. It provides a userspace API to process UVC control requests
¦ and stream video data to the host.
¦ Say "y" to link the driver statically, or "m" to build a
¦ dynamically linked module called "g_webcam".
endchoice
- choice 开始,endchoice 结束。
- choice 中间可以加入其他配置,以及 choice 嵌套
- 他们之间只能有一个被设置为 y:表示编译进内核
- 他们之间可以有多个被设置为 m:表示编译成模块
3.4.2. 示例
choice
prompt "The maximal size of fifo"
default USB_FIFO_512
config USB_FIFO_512
bool "512"
config USB_FIFO_1024
bool "1024"
config USB_FIFO_3072
bool "3072"
endchoice
3.5. menuconfig
menuconfig XXX和config XXX类似, 唯一不同的是该选项除了能设置y/m/n外,还可以实现菜单效果(能回车进入该项内部)。
比如 usb gadget 驱动就是 menuconfig 配置

3.5.1. 语法
menuconfig常用格式有2种:
menuconfig M
if M
config C1
config C2
endif
或者
menuconfig M
config C1
depends on M
config C2
depends on M
第1项menuconfig M跟config M语法是一样的, 不同之处在于menuocnfig M后面可以跟着好几个依赖于M的config C1、config C2等子配置项.
3.6. if/endif
3.6.1. 语法
在上面的menuconfig中就有if/endif的使用,它的语法如下:
if xxx
endif
3.6.2. 示例
if USB_GADGET
config USB_GADGET_DEBUG
boolean "Debugging messages (DEVELOPMENT)"
depends on DEBUG_KERNEL
help
¦ Many controller and gadget drivers will print some debugging
¦ messages if you use this option to ask for those messages.
¦ A
......
endif
只有定义了 USB_GADGET ,以下部分才会显示出来。
3.7. source
3.7.1. 语法
source 语句用于读取另一个文件中的 Kconfig 文件, 比如driver/usb/Kconfig 中就包含了其他Kconfig:
source "drivers/usb/gadget/Kconfig"
3.8. comment
3.8.1. 语法
comment 语句出现在界面的第一行,用于定义一些提示信息,如:

界面如下:

4. 总结
本文主要分析了 menuconfig 生成和使用过程,并且介绍了Kconfig 常见用法及语法介绍。
有关 config/menu/menuconfig/choice等 Kconfig语法本质上就是脚本语言,也存在对应的相互组合关系,每种语法规则不是独立的。熟悉了 Kconfig 基本组织规则,那么就熟悉了 内核配置过程。无论是 linux 还是 rtos 只要是基于menconfig 配置的都是一通百通。
新闻来源:嵌入式大杂烩,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。


