1、概述
在linux编写驱动的过程中,有两个文件是我们必须要了解和知晓的。这其中,一个是Kconfig文件,另外一个是Makefile文件。如果大家比较熟悉的话,那么肯定对内核编译需要的.config文件不陌生,在.config文件中,我们发现有的模块被编译进了内核,有的只是生成了一个module。
首先我们来学习什么Makefile,什么是Kconfig ,什么是.config
Makefile:一个文本形式的文件,其中包含一些规则告诉make编译哪些文件以及怎样编译这些文件。
Kconfig:一个文本形式的文件,其中主要作用是在内核配置时候,作为配置选项。
.config:文件是在进行内核配置的时候,经过配置后生成的内核编译参考文件。
Makefile2.6内核的Makefile分为5个组成部分:
1. 最顶层的Makefile
2. 内核的.config配置文件
3. 在arch/$(ARCH) 目录下的体系结构相关的Makefile
4. 在s目录下的 Makefile.* 文件,是一些Makefile的通用规则
5. 各级目录下的大概约500个kbuild Makefile文件
顶层的Makefile文件读取 .config文件的内容,并总体上负责build内核和模块。Arch Makefile则提供补充体系结构相关的信息。 s目录下的Makefile文件包含了所有用来根据kbuild Makefile 构建内核所需的定义和规则。
这中间,我们如何让内核发现我们编写的模块呢,这就需要在Kconfig中进行说明。至于如何生成模块,那么就需要利用Makefile告诉编译器,怎么编译生成这个模块。模仿其实就是最好的老师,我们可以以内核中经常使用到的网卡e1000模块为例,说明内核中是如何设置和编译的。
首先,我们可以看一下,在2.6.32.60中关于e1000在Kconfig中是怎么描述的,
上面的内容是从drivers/net/Kconfig中摘录出来的。内容看上去不复杂,最重要的就是说明了模块的名称、用途、依赖的模块名、说明等等。只要有了这个说明,我们在shell下输入make menuconfig的时候,理论上我们就应该可以看到Intel(R)PR0/1000 Gigabit Ethernet support 这个选项了,输入y表示编译内核;输入n表示不编译;输入m表示模块编写,这是大家都知道的。
那么,有了这个模块之后,需要编译哪些文件中,我们在drivers/net/Makefile看到了这样的内容,
显然,这段代码只是告诉我们,要想编译e1000,必须要包含e1000这个目录,所以e1000目录下必然还有一个Makefile,果不其然,我们在e1000目录下果然找到了这个Makefile,内容如下,
看了这个文件,其实大家心理就应该有底了。原来这个e1000模块最终生成的文件就是e1000.ko,依赖的文件就是e1000_main.c、e1000_hw.c、e1000_ethtool.c、e1000_param.c这四个文件。只要CONFIG_E1000被设置了,那么这个模块就会被正常编译。我们要做的就是打开这个开关就可以了,剩下kernel会帮我们搞定一切。当然,如果大家想把这个模块拿出来,自己用一个独立的module编译也是可以的。但是我们在menuconfig中没有找到这个配置选项?这是怎么回事呢?
2、Kconfig 语法
由于没有找到这个配置选项,我们只能从Kconfig的语法开始分析了。
2.1. 基本构成
基本构成包括五种,menu/endmenu,menuconfig,config,choice/endchoice,source。下面就对每种详细介绍:
(1) menu/endmenu
menu的作用,可以理解成一个目录,menu可以把其中一部分配置项包含到一个menu中,这样有利于配置的分类显示。menu与endmenu是一组指令,必须同时出现。menu和endmenu中包含的部分就是子目录中的配置项。
比如,在init/Kconfig中24行(可能不同)显示为:
menu "General setup"
这样,就会生成一个目录,特征就是右侧会出现一个箭头,如图1中第一行。当点击确认键时,会进入这个菜单项。make menuconfig 进入的第一个界面 基本所有选项都称为menu.
(2)menuconfig
menuconfig有点类似menu,但区别就在于menu后面多了一个config,这个menu是可以配置的,如图2中的第二行,前面比 menu类型多了一个方框,通过空格可以修改这个配置项的选中状态。而且从格式上来看,也是有区别的。如下图所示椭圆的都是menu 长方形的就是menuconfig了。
menuconfig MODULES bool "Enable loadable module support"config if MODULES xx endif
也就是说,配置项是位于if和endif中。其中的部分就是MODULES子目录显示的内容。如果选中了MODULE,那么if和endif中的内容可以显示。如果没有定义,就只能进入一个空目录。
(3) config
config是构成Kconfig的最基本单元,其中定义了配置项的详细信息。定义的格式参考arch/arm/Kconfig中的第8行。
config ARM bool default y select xxxxxxxxxx help ???????????
详细可以参阅 http://blog.csdn.net/xy010902100449/article/details/45131973
可知,config需要定义名称,与menuconfig相同。这个名称不但用于裁剪内核中,还用于配置项之间的相互依赖关系中。
config的类型有5种,分别是bool(y/n),tristate(y/m/n),string(字符串),hex(十六进 制),integer(整数)。其中,需要特别介绍一下bool和tristate,bool只能表示选中和不选,而tristate还可以配置成模块 (m),特别对于驱动程序的开发非常有用。
其他语法如下:
1) prompt:提示,显示在make menuconfig中的名称,一般省略。下面两种写法相同。 a. bool “Networking Support” b. bool prompt “Networking Support” 2) default:默认值 一个配置项可以有多个默认值,但是只有第一个被定义的值是有效的。 3) depends on/requires:依赖关系 如果依赖的配置项没有选中,那么就当前项也无法选中。 4) select:反向依赖 如果当前项选中,那么也选中select后的选项。 5) range:范围,用于hex和integer range A B表示当前值不小于A,不大于B 6) comment:注释(4) choice
choice的作用,多选一,有点像MFC中的Radio控件。
可见,choice有点类似于menu,是在子窗口里选择,但是不同的是子窗口中只能选择一项。在prompt后会显示当前选择项的名称。
5) source
source只是将另外一个Kconfig文件直接复制到当前位置而已。但它的作用也是明显的,可以将这个系统贯穿在一起。从开始位置arch/arm/Kconfig,来将整个系统都作为配置型。
由此我们可以知道,之前那个选项没有出现,是由于depends on 依赖条件不符合。