摘要:在进行内核编译的时候,内核配置无疑是其中最为重要的环节,直接决定了编译的内核是否能够满足要求。而且,对于新加入的内核特性,我们往往无法在make menuconfig中找到相应的选项。本文主要为你解决如下问题:1)linux内核编译之前,配置文件的读取顺序是什么?2)对于比较新的内核特性,我们无法在.config之中找到某个配置,应该如何处理?3)如何将自己新添加的驱动添加进入内核?
Linux内核的配置系统由三个部分组成,分别是:
1)、Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则;
2)、配置文件(config.in(2.4内核,2.6内核)):给用户提供配置选择的功能;
3)、配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图形界面以及基于 Xwindows 图形界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。
这些配置工具都是使用脚本语言,如 Tcl/TK、Perl 编写的(也包含一些用 C 编写的代码)。本文并不是对配置系统本身进行分析,而是介绍如何使用配置系统。所以,除非是配置系统的维护者,一般的内核开发者无须了解它们的原理,只需要知道如何编写 Makefile 和配置文件就可以。
当我们在执行make menuconfig这个命令时,系统到底帮我们做了哪些工作呢?
这里面一共涉及到了一下几个文件我们来一一讲解
(1)Linux内核根目录下的scripts文件夹
(2)arch/$ARCH/Kconfig文件、各层目录下的Kconfig文件
(3)Linux内核根目录下的makefile文件、各层目录下的makefile文件
(4)Linux内核根目录下的的.config文件、arm/$ARCH/下的config文件
(5)Linux内核根目录下的 include/generated/autoconf.h文件
1)scripts文件夹存放的是跟make menuconfig配置界面的图形绘制相关的文件,我们作为使用者无需关心这个文件夹的内容
2)当我们执行make menuconfig命令出现上述蓝色配置界面以前,系统帮我们做了以下工作:
首先系统会读取arch/$ARCH/目录下的Kconfig文件生成整个配置界面选项(Kconfig是整个linux配置机制的核心),那么ARCH环境变量的值等于多少呢?
它是由linux内核根目录下的makefile文件决定的,在makefile下有此环境变量的定义:
或者通过 make ARCH=arm menuconfig命令来生成配置界面,默认生成的界面是所有参数都是没有值的
比如教务处进行考试,考试科数可能有外语、语文、数学等科,这里相当于我们选择了arm科可进行考试,系统就会读取arm/arm/kconfig文件生成配置选项(选择了arm科的卷子),系统还提供了x86科、milps科等10几门功课的考试题
Koncfig文件包含了配置选项的依赖关系,层次关系,各个选项的默认值。
3)假设教务处比较“仁慈”,为了怕某些同学做不错试题,还给我们准备了一份参考答案(默认配置选项),存放在arch/$ARCH/configs下,对于arm科来说就是arch/arm/configs文件夹:
此文件夹中有许多选项,系统会读取哪个呢?内核默认会读取linux内核根目录下.config文件作为内核的默认选项(试题的参考答案),我们一般会根据开发板的类型从中选取一个与我们开发板最接近的系列到Linux内核根目录下(选择一个最接近的参考答案)
#cp arch/arm/configs/s3c2410_defconfig .config
4).config
假设教务处留了一个心眼,他提供的参考答案并不完全正确(.config文件与我们的板子并不是完全匹配),这时我们可以选择直接修改.config文件然后执行make menuconfig命令读取新的选项
但是一般我们不采取这个方案,我们选择在配置界面中通过空格、esc、回车选择某些选项选中或者不选中,最后保存退出的时候,Linux内核会把新的选项(正确的参考答案)更新到.config中,此时我们可以把.config重命名为其它文件保存起来(当你执行make distclean时系统会把.config文件删除),以后我们再配置内核时就不需要再去arch/arm/configs下考取相应的文件了,省去了重新配置的麻烦,直接将保存的.config文件复制为.config即可.
5)经过以上两步,我们可以正确的读取、配置我们需要的界面了
那么他们如何跟makefile文件建立编译关系呢?
当你保存make menuconfig选项时,系统会除了会自动更新.config外,还会将所有的选项以宏的形式保存在
Linux内核根目录下的 include/generated(linux)/autoconf.h文件下,它实际上是makefile文件读取的内容
内核中的源代码就都会包含以上.h文件,跟宏的定义情况进行条件编译。
当我们需要对一个文件整体选择如是否编译时,还需要修改对应的makefile文件,例如:
我们选择是否要编译s3c2410_ts.c这个文件时,makefile会根据CONFIG_TOUCHSCREEN_S3C2410来决定是编译此文件,此宏是在Kconfig文件中定义,当我们配置完成后,会出现在.config及autconf中,至此,我们就完成了整个linux内核的编译过程。
最后我们会发现,整个linux内核配置过程中,留给用户的接口其实只有各层Kconfig、makefile文件以及对应的源文件。
比如我们如果想要给内核增加一个功能,并且通过make menuconfig控制其生成过程
首先需要做的工作是:修改对应目录下的Kconfig文件,按照Kconfig语法增加对应的选项;
其次执行make menuconfig选择编译进内核或者不编译进内核,或者编译为模块,.config文件和autoconf.h文件会自动生成;
最后修改对应目录下的makefile文件完成编译选项的添加;
最后的最后执行make zImage命令进行编译。
总结一下,这个过程大致是这样的:各个目录之下存在Kconfig文件,里面的内容是相关的选项,depends和select;执行make menuconfig命令以后,会读取这些Kconfig里面的配置选项(配置选项的默认值也在各个Kconfig文件之中),生成如下图的图形界面。
我们对相关的symbol进行配置,然后点击保存,就写入了.config文件和相应头文件。大致如此:Kconfig *******menuconfig*********.config&& include/generated/autoconf.h************make
下面我们以前面做过的模块实验为例,讲解如何通过make menuconfig机制将前面单独编译的模块编译进内核或编译为模块
假设我已经有了这么一个驱动:
modules.c
modules.o必须跟你加入的.c文件名一致
最后执行:make zImage modules就会被编译进内核中
第三步:
跟我们前面讲的单独编译模块效果一样,也会生成一个模块,将它考入开发板执行insmod moudles.ko,即可将生成的模块插入内核使用。
1)linux内核编译之前,配置文件的读取顺序是什么?
参考第二部分的总结
2)对于比较新的内核特性,我们无法在.config之中找到某个配置,应该如何处理?
如果一个配置没有出现在.config之中,我们首先要在make menuconfig的界面中进行寻找,如果在这个界面中能够找到,那么多半是我们没有将这个对应symbol的depends满足,所以导致config之中没有相关的选项。此时,我们只要查看相关symbl的depends,然后满足它们即可,就可以在.config之中找到相应选项。如果在make menuconfig的界面中也无法找到,说明Kconfig之中没有相关的配置选项,就说明它还没有被编入内核。
3)如何将自己新添加的驱动添加进入内核?
参看第三部分
1)比那一centos 6.3出错“crypto/signature/ksign-publickey.c: key.h: No such file or directory”
解决方法:
run make menuconfig.
1) Select "Enable loadable module support", then "Module signature verification (EXPERIMENTAL)". Disable it.
2) Then go back to the main menu, select "Cryptographic API" then "In-kernel signature checker (EXPERIMENTAL)" and disable that one too.
Then go back again, save your config and make your kernel. At least, it will pass this phase successfully.
注意:VERSION,PATCHLEVEL,SUBLEVEL之间是会自动加上“.”的,但是EXTRAVERSION之前不会自动加“.”。版本控制是通过脚本文件scripts/setlocalversion来执行的,如果CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCALVERSION_AUTO=N:
如果没有定义LOCALVERSION,版本号后面会添加“+”号
没有定义LOCALVERSION,版本后不会添加“+”
如果既不想添加字符,又不想有“+”号:不定义CONFIG_LOCALVERSION_AUTO,将LOCALVERSION变量定义为空:LOCALVERSION=
自定义版本号的方法:
在scripts/setlocalversion文件中还有有这么一段:
# localversion* files in the build and source directory
res="$(collect_files localversion*)"
if test ! "$srctree" -ef .; then
res="$res$(collect_files "$srctree"/localversion*)"
fi
# CONFIG_LOCALVERSION and LOCALVERSION (if set)
res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
由此可看出,如果想往版本号里添加字符,有几种方式:
1. 使用LOCALVERSION变量(或者在命令行,或者添加为环境变量)
2. 在linux-2.6.35目录下添加文件localversion,文件内容会自动添加到版本号里去。
3. 定义CONFIG_LOCALVERSION变量
4. 如果linux-2.6.35目录下有文件localversion(其内容为.33),也使用了LOCALVERSION变量,也定义了CONFIG_LOCALVERSION=".XYZ"。
make LOCALVERSION=.44 include/config/kernel.release
此时对2.6.35.7的内核,include/config/kernel.release的内容为2.6.35.7.33.XYZ.55。
可看到添加的三种字符的顺序:文件localversion内容在前,然后是CONFIG_LOCALVERSION的值,最后是LOCALVERSION的值。
本文来源:
linux 内核编译:内核配置原理与常见配置问题的解决方法:http://blog.csdn.net/trochiluses/article/details/9663743
外部参考:http://blog.csdn.net/dianhuiren/article/details/6917132
【2】linux内核配置系统解析:http://www.ibm.com/developerworks/cn/linux/kernel/l-kerconf/
【3】linux内核版本号:http://blog.csdn.net/adaptiver/article/details/7225980