有过 linux 内核开发经验的人,对menuconfig 不会陌生。对于各类内核,只要是支持menuconfig 配置界面,都是使用Kconfig。
换言之:
故我们只要熟悉了Kconfig 的语法规则,就熟悉了 menuconfig的应用。这样对于基于menconfig 配置界面的各类内核都能得心应手了。
linux 内核的配置界面如下:
思考两个问题:
熟悉内核的都知道, 配置内核的过程中只需要执行 make menconfig 界面就自动出来了。
那么,在执行make mneconfig 的过程中到底发生了什么?
Makefile
scripts/kconfig/Makefile
make menuconfig 过程:
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;
}
我们可以看到,干了三件事:
最终会将配置界面设置保存成 .config 文件。
我们在编译内核前通过有两种操作:
make xxx_defconfig 操作会生成 conf 应用,并且解析xxx_defconfig。make menuconfig 操作会生成 mconf 应用,会将我们配置的选项保存成 .config
当我们在执行编译内核的时候,会自动将 .config 里面的配置 转换成相应的宏到 autoconf.h 里面。
//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
当我们配置生成好 .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();
linux 内核主要是基于 Kconfig 来组织menuconfig从而达到配置内核的目的。那么主要从两方面入手。
本质上.config 和 xxx_defconfig 是同一文件。
在编译内核的过程中会将 .config 转换为相应的宏,包含在头文件autoconf.h 中,这样就可以供内核使用了。
故我们只需要掌握了 Kconfig 配置,就基本掌握了menuconfig 配置和添加流程。
在Kconfig文件中,假设配置项的名字是XXX,在.config文件中:
如图 USB Webcam Gadget 就是一个配置项:
我们还是以一个例子说明:
# 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 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 选中才能生效。
如图 USB audio choice 包含两个配置项。UAC1_PLAY 和 UAC1_CAP
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配置, 当然也可以包含 其他语法。
menu "test menu"
config TEST_MENU_A
tristate "menu test A"
config TEST_MENU_B
bool "menu test B"
default n
endmenu
test menu 包含两个配置项:
如图为 linux usb gadget 驱动,支持各种gadget 设备:
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
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
menuconfig XXX和config XXX类似, 唯一不同的是该选项除了能设置y/m/n外,还可以实现菜单效果(能回车进入该项内部)。
比如 usb gadget 驱动就是 menuconfig 配置
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等子配置项.
在上面的menuconfig中就有if/endif的使用,它的语法如下:
if xxx
endif
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 ,以下部分才会显示出来。
source 语句用于读取另一个文件中的 Kconfig 文件, 比如driver/usb/Kconfig 中就包含了其他Kconfig:
source "drivers/usb/gadget/Kconfig"
comment 语句出现在界面的第一行,用于定义一些提示信息,如:
界面如下:
本文主要分析了 menuconfig 生成和使用过程,并且介绍了Kconfig 常见用法及语法介绍。
有关 config/menu/menuconfig/choice等 Kconfig语法本质上就是脚本语言,也存在对应的相互组合关系,每种语法规则不是独立的。熟悉了 Kconfig 基本组织规则,那么就熟悉了 内核配置过程。无论是 linux 还是 rtos 只要是基于menconfig 配置的都是一通百通。
猜你喜欢:
分享两点提高编程能力的建议!
嵌入式如何进行架构设计?
干货 | 嵌入式OTA升级实现原理
学STM32需要学会哪些才建议去学Linux?
一个小巧灵活的按键处理库!
嵌入式 C 结构体内存对齐
在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。
点击阅读原文,查看更多分享。