menuconfig是一套图像化配置工具,由ncurses库提供软件支持。ncurses库提供了一系列的函数以便使用者调用它们去生成基于文本的用户界面。
menuconfig本身的软件只负责提供menuconfig工作的这一套逻辑,比如说通过上下左右调整光标,Enter选中等,并不负责提供内容。menuconfig运行之后会读取Kconfig、读取/写入.config文件,Kconfig提供菜单项的内容,.config用来记录菜单项的选择值。
内核源码目录下make menuconfig就会进来,箭头按键导航整个菜单,回车按键选择子菜单(注意选项后面有 —>的选项才是有子菜单的,没有这个标识的没有子菜单),高亮的字母是热键(快捷键),键盘按键Y、N、M三个按键的作用分别是将选中模块编入、去除、模块化。双击ESC表示退出,按下?按键可以显示帮助信息,按下/按键可以输入搜索内容来全局搜索信息(类似于vi中的搜索),[ ]不可以模块化,< >的才可以模块化。
注:linux内核中一个功能模块有三种编译方法:一种是编入、一种去去除、一种是模块化。所谓编入就是将这个模块的代码直接编译连接到zImage中去,去除就是将这个模块不编译链接到zImage中,模块化是将这个模块仍然编译,但是不会将其链接到zImage中,会将这个模块单独链接成一个内核模块.ko文件,将来linux系统内核启动起来后可以动态的加载或卸载这个模块。
在menuconfig中选项前面的括号里,*表示编入,空白表示去除,M表示模块化。
执行make menuconfig的时候,会执行顶层目录下的Makefile。
%config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
$(build)=scripts/kconfig,build是编译规则,$(build)=scripts/kconfig
实质是:-f scripts/kconfig/Makefile
则:$(Q)$(MAKE) $(build)=scripts/kconfig $@ 等同于
make -f scripts/kconfig/Makefile menuconfig
-f:指定执行某个Makefile文件,表示到scripts/kconfig目录下Makefile文件中,生成目标menuconfig。
Q的值根据KBUILD_VERBOSE的值来决定,Q=空时会打印命令信息,Q=@时隐藏命令信息。
MAKE为系统内置变量,可以参考这篇文章打印。
绘制图形和解析这个界面的文件都会在scripts/kconfig目录下面,比较重要的文件有mconf.c和lxdialog目录。
接下来,scripts/kconfig/Makefile 找到目标所在的代码:
menuconfig: $(obj)/mconf
$< $(Kconfig)
obj := $(CURDIR)
Kconfig := arch/$(SRCARCH)/Kconfig
SRCARCH := $(ARCH)
而变量在顶层目录的Makefile中早已赋值arm,所以:
menuconfig: scripts/kconfig/mconf
scripts/kconfig/mconf arch/arm/Kconfig
当我们执行命令make menuconfig时,(1)先创建两个二级目录include /linux 和 include/config,(2)接着把scripts/kconfig/里面的可执行文件mconf运行起来,有能力的话可以详看scripts/kconfig/mconf.c,根据文件arch/arm/kconfig内容,显示出一个菜单界面。其实,mconf运行起来,首先是“画出”菜单界面(显示内容则根据各级目录的Kconfig文件),然后查看源码顶层目录有没有存在.config文件,若没有,则按照默认显示到菜单里面;若存在.config,则会把它读出来存到内存某块区域,在逐行逐行解析它的内容,再把读出的内容更新到菜单。最后会保存在源码顶层的.config文件中。
kconfig的总入口是arch/arm/kconfig,不是源码顶层的kconfig,入口一定是根据某款平台的。
bool:[ ]有两种状态,*代表选中,空代表未选中;
tristate:< >有三种状态,*代表选中,空代表未选中,M代表模块;
string:( )存放十进制或者十六进制字符串;
如果配置程序选择了使用它,那么就用它配置程序的标题栏。
mainmenu "Linux Kernel Configuration"
config ARM
bool
default y
select HAVE_AOUT
select HAVE_IDE
开启一个新的配置选项入口,下面的行定义了配置选项的属性,属性可以是配置输入提示、依赖、帮助文档和默认值等,一个配置选项可以被多次定义,但是每一次定义只有单一的输入提示,并且类型不能冲突。
config MODVERSIONS
bool "Set version information on all module symbols"
depends on MODULES
help
Usually, modules have to be recompiled whenever you
switch to a newkernel. ...
输入提示作用,下面两种方式,效果相同。
bool "Networking support"
and
bool
prompt "Networking support"
depends on 表示此选项会依赖其它选项的配置,也就是BAR被选择之后,该选项才能被选择;select 表示反向依赖,如果当前项选中,那么也选中select后的选项。
用于设定默认值,y表示该选项默认被选择上。
bool "foo" if BAR
default y if BAR
and
depends on BAR
bool "foo"
default y
定义一个菜单入口, 表示Network device support是一个菜单选项。
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
将另外一个Kconfig文件直接复制到当前位置,可以将这个系统贯穿在一起。从开始位置arch/arm/Kconfig,来将整个系统都作为配置型。
config ARM_L1_CACHE_SHIFT_6
bool
help
Setting ARM L1 cache line size to 64 Bytes.
source "init/Kconfig"
帮助信息,告诉我们这个配置项的含义,以及如何去配置他。
“.config文件中每一行都是一个配置项,从.config文件的规模可以看出linux内核的可配置项有两三千个。所以linux内核是高度可配置的,而且linux内核的所有配置项很难全部搞明白。因为linux内核的配置项太多太繁杂超出了人的大脑能够记忆和处理的数量级,因此linux内核不像uboot那样直接手工配置,而是发明了一个图形化的配置工具menuconfig。”
menuconfig的终极目标就是让我们更容易地配置.config文件。一般厂商会提供他们配置好的.config文件,里面配置好了大部分的必要功能,如果我们自己需要修改,那么就可以通过menuconfig来修改配置。
(1)menuconfig中config后面空格隔开的大写字母表示的类似于 NETDEVICES 的就是这个配置项的配置项名字,这个字符串前面添加 CONFIG_ 后就构成了.config中的配置项名字。
(2)这个.config中的配置值(=y、=m、=n)会影响最终的编译链接过程。如果=y则会被编入(built-in),如果=m会被单独连接成一个ko模块,如果=n则对应的代码不会被编译,这些都是通过makefile实现的。
(3).config中的配置值指导整个编译连接过程。
参考文章: