在配置内核的时候会有很多配置方法:
- make menuconfig
- make xxx_defconfig
- 直接修改.config
注意: 其中menuconfig
是一个图形化配置工具,在后面我们会着重介绍;xxx_defconfig
是在arch/arm/configs
文件夹下的一些默认配置文件;.config
是编译的时候系统默认读取的配置文件,如果直接修改.config
,不一定会生效,因为有些配置可能存在依赖关系,make
时会根据依赖关系,进行规则的检查,直接修改.config
有时无效,所以不推荐直接修改。
通过以上我们也可以知道,如果想要使用默认配置文件,也即xxx_defconfig
,那么我们除了可以直接执行·make xxx_defconfig·,还可以直接把xxx_defconfig
里的内容复制到我们的.config
文件中,这样make
的时候不用加配置文件就可以自动去读取.config
配置文件。
menuconfig及其类似的几款配置工具:
make config
(基于文本的最为传统的配置界面,不推荐使用)make menuconfig
(基于文本选单的配置界面,字符终端下推荐使用)make xconfig
(基于图形窗口模式的配置界面,Xwindow
下推荐使用)make oldconfig
(如果只想在原来内核配置的基础上修改一些小地方,这种方法会省去不少麻烦)
以上四种配置方法它们的目的都是生成一个.config
文件,这几个命令中,make xconfig
的界面最为友好,如果你可以使用Xwindow
,你就用这个好了,这个比较方便,也好设置;如果你不能使用Xwindow
,那么就使用make menuconfig
好了,界面虽然比上面一个差点,但是比另外两个方法要好多了。
menuconfig
是一套图像化配置工具,由ncurses
库提供软件支持。ncurses
库提供了一系列的函数以便使用者调用它们去生成基于文本的用户界面。menuconfig
本身的软件只负责提供menuconfig
工作的这一套逻辑,比如说通过上下左右调整光标,Enter选中等,并不负责提供内容。
menuconfig
运行之后会读取Kconfig
文件、读取/写入.config
文件,Kconfig
文件提供菜单项的内容,.config
用来记录菜单项的选择值。
linux内核
中一个功能模块有三种编译方法:一种是编入、一种是去除、一种是模块化。在进行配置的时候对应着有三种选择:
-
Y
-将该功能编译进内核 -
N
-不将该功能编译进内核 -
M
-将该功能编译成可以在需要时动态插入到内核中的模块
所谓编入就是将这个模块的代码直接编译链接到zImage
中去,去除就是将这个模块不编译链接到zImage
中,模块化是将这个模块仍然编译,但是不会将其链接到zImage
中,会将这个模块单独链接成一个内核模块.ko
文件,将来linux
系统内核启动起来后可以动态的加载或卸载这个模块。
[ ]、< >、()
的意思
在menuconfig
中选项前面的括号里,*
表示编入,空白
表示去除,M
表示模块化。
-
[ ]
:只有编入和去除两种状态,也即此选项不可以模块化 -
< >
:三种编译状态都有 -
( )
:存放十进制或十六进制或字符串;
其实打开方式很简单,但是我之前还是踩了坑,我们只需要执行make menuconfig
即可。但是该命令执行的位置是需要特别注意的,不是直接在根目录下执行,而是找到你下载的linux内核源码
,然后在arch
文件夹所在的同级路径下打开命令行输入make menuconfig
。如果缺少一些依赖库,可以根据错误去安装,这里就不说了。
前面我们也说了,menuconfig
运行之后会读取Kconfig
文件、读取/写入.config
文件,Kconfig
文件提供菜单项的内容,.config
用来记录菜单项的选择值。其实Kconfig
我们也可以看作一个编程语言,那么Kconfig
文件我们应该怎么编写呢?它又有哪些语法和规则呢?
kconfig
的总入口是arch/arm/kconfig
,不是源码顶层的kconfig
,因为入口一定是具体对应某一款平台的。
1.tristate、bool、string
- bool:表示有两种状态,选项前会有[ * ]/[ ],分别代表编入和去除
- tristate:表示有三种状态,选项前会有< * >/< >/< M > ,分别代表编入、去除、编译成模块
- string:表示这是十进制或者十六进制或者字符串,选项前会有( ),括号里有相应的内容
2.mainmenu
如果在配置界面选择了它,那么就用它配置标题栏,也即它后面的字符串会显示在配置界面的标题栏中。
mainmenu "Linux Kernel Configuration"
config ARM
bool
default y
select HAVE_AOUT
select HAVE_IDE
3.config
开启一个新的配置选项入口,下面的行定义了配置选项的属性,属性可以是配置输入提示、依赖、帮助文档和默认值等,一个配置选项可以被多次定义,但是每一次定义只有单一的输入提示,并且类型不能冲突。
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.
4.prompt
输入提示作用,下面两种方式,效果相同。
bool "Networking support"
bool
prompt "Networking support"
5.depends on、select
depends on
表示此选项会依赖其它选项的配置,也就是depends on
后面指定的选项被选择之后,该选项才能被选择;select
表示反向依赖,如果当前项选中,那么也选中select
后指定的选项。
6.default
用于设定默认值,y表示该选项默认被选择上。
7.menu
定义一个菜单入口, 表示Network device support是一个菜单选项。菜单选项不是一个功能,也即config
后面的指定的功能选项,它只是表示只有进入这个菜单里面,才能去配置里面的功能选项。
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
8.source
将另外一个Kconfig
文件直接复制到当前位置,可以将整个系统贯穿在一起,也可以使我们避免重复写一些内容。假如我在linux-4.1.15/drivers/
下新建了一个hello
文件夹,用来保存我新写的hello world
驱动程序,那么在linux-4.1.15/drivers/hello
下肯定要有一个Kconfig
文件,此时我们就需要在上一级的,也就是linux-4.1.15/drivers/
下的Kconfig
文件中添加一句source "drivers/hello/Kconfig"
config test
bool
help
Setting ARM L1 cache line size to 64 Bytes.
source "arch/arm/Kconfig"
9.help
帮助信息,告诉我们这个配置项的含义,以及如何去配置他。
剩下的一些语法就需要我们自己不断的积累和查找资料了,这里就不一个一个的说了。
四、配置过程中涉及到的几个主要的文件- Kconfig
- Makefile
- .config
它们之间的关系如下:
- 我们通过编写
Kconfig
在配置菜单上添加所需的配置项 - 配置项被配置成
Y、N、M
会影响.config
文件中的CONFIG_XXX
变量的值。 .config
中的配置值(=y、=m、=n
)会影响最终的编译链接过程。如果=y
则会被编入,如果=m
会被单独连接成一个.ko
模块,如果=n
则对应的代码不会被编译。而编译与不编译就是makefile
根据CONFIG_XXX
变量的值来决定的。
假如我们添加了一个test
功能项,配置好之后这三个文件里的相关内容如下:
-
Kconfig中:
config test
-
makefile中:
obj-$(test) += xxxxx.c
-
.config中:
CONFIG_test=y
假如我写了一个简单的在入口函数中输出hello world
的驱动并编译进内核。那么整个步骤大概是这样的:
hello.c
#include
#include
#include
static int first_drv_init(void)
{
printk("------------------hello world !--------------------");
return 0;
}
static void first_drv_exit(void)
{
printk("------------------exit hello world!--------------------");
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
Makefile
obj-$(CONFIG_HELLO) += hello.o
Kconfig:
config HELLO
tristate "Hello Worldfor fengyuwuzu"
help
Hello forfengyuwuzu
config HELLO决定名字:CONFIG_HELLO。 Hello World for fengyuwuzu:决定了在make menuconfig时显示的名字
2、修改上一级(linux-4.1.15/drivers
下)的Makefile、Kconfig
Makefile:
obj-y += hello/
Kconfig:
source "drivers/hello/Kconfig"
3、make menuconfig
查看内核启动Log,helloworld 出来了就说明hello.c成功编进内核
至此,关于menuconfig
我想说的已经说得差不多了,重要的在于理清思路,具体的一些细节肯定还需要我们自己去查资料和总结。
参考文章1:浅谈内核的Makefile、Kconfig和.config文件
参考文章2:嵌入式Linux–menuconfig详解