首页 > 代码库 > Kernel 编译配置机制

Kernel 编译配置机制

      编译kernel前需要一个配置相关的编译选项,最终的配置文件就是kernel根目录路下的 .config 文件


一:.config


这个文件里面保存的是kernel的配置选项,格式如下:

CONFIG_XX_XX=y/n/m/0xFFFFFF/32/”XXXXXXX”

这个文件由/scripts/kconfig/mconf.c负责解析,然后解析该文件并将解析结果以宏定义的形式写入到/include/generated/autoconf.h中。/include/generated/autoconf.h将会被/include/linux/kconfig.h包含,
因此,需要关心配置情况的内核源文件只需要#include <linux/config.h>即可。




二:make menuconfig

分析一下这个主make menuconfig在Makefile中的大体流程,我的内核版本:

VERSION = 3
PATCHLEVEL = 1
SUBLEVEL = 10
EXTRAVERSION =

make menuconfig 与主Makefile 中的%config 目标匹配:
依赖关系:

%config: scripts_basic outputmakefile FORCE
	./mpatch_gen.sh
	$(Q)mkdir -p include/linux include/config
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

依赖 scripts_basic outputmakefile FORCE 这三个目标

1:FORCE

其中 FORCE 为伪目标

PHONY += FORCE
FORCE:

PHONY 中的项目被称为伪目标,伪目标作为另外一个目标的依赖时,每次执行此规则是,伪目标所定义的指令都会执行。这个规则没有命令也没有依赖,它的目标也不是一个存在的文件名。在执行此规则时,目标FORCE总会被认为是最新的。这样当它作为其它规则的依赖时,因为依赖总被认为被更新过的,所以那个规则的中定义的命令总会被执行。

在这里 每次执行make menuconfig 时候 都认为 FORCE 是更新过的 ,下面的三条命令也一定会执行!

2:scripts_basic

# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

build变量定义在scripts/kbuild.include中:

###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj

这样看,上面的规则可以写成:

$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=scripts/basic

这个规则的命令最终会进入scripts目录,执行Makefile.build文件,并传递参数obj=scripts/basic.

这个往里面走就是到scripts/Makefile.build 中:

src := $(obj)

包含Makefile文件:
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)

第一个目标,

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) 	 $(subdir-ym) $(always)
	@:

到这里其实只是构建了 $(builtin-target)等变量指定的目标,$(always)变量在这个Makefile中定义。

3:outputmakefile

看一下依赖关系:
PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile 	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

当变量$(KBUILD_SRC)为空的时候,运行一个shell脚本scripts/mkmakefile,并传递四个参数。这个脚本主要是在$(objtree)参数指定的目录中生成一个Makefile文件。由于这里KBUILD_SRC为空,所以这个脚本并不会被执行。

4:规则命令

处理完上面的三个依赖之后,就执行接下来的命令,

我这边运行了一个shell脚本,配置了mpatch,然后创建了两个目录,按照上面的规则展开第三条命令:

$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build  obj =scripts/kconfig menuconfig

这个命令依然是执行scripts/Makefile.build这个makefile文件。并执行它里面menuconfig的规则。根据上面的分析,在Makefile.build会包含scripts/kconfig/Makefile文件。然后执行以menuconfig为目标的规则:

menuconfig: $(obj)/mconf
	@scripts/checkconfig/check-config.sh
	@echo "*** jscese test  ‘$(Kconfig)‘"
	$< $(Kconfig)

这里调用了mconf:

# mconf:  Used for the menuconfig target
#         Utilizes the lxdialog package

我这里还运行了check脚本,判断目前的.config文件的内容,检测里面的参数。
然后就运行加载了$(Kconfig)

ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
Kconfig := Kconfig

$(KBUILD_KCONFIG)是没有定义的,所以首先被调用加载的 是kernel 根目录下的Kconfig 文件



三:Kconfig

上面从make menuconfig中分析最后调用的也就是根目录的Kconfig文件,这也是第一个加载的Kconfig文件:

#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "Linux/$ARCH $KERNELVERSION Kernel Configuration"

config SRCARCH
	string
	option env="SRCARCH"
    
source "arch/$SRCARCH/Kconfig"

这里的$(SRCARCH) 在主Makefile 里面定义,我的这是arm平台,流程如下:

target_ARM = $(shell cat .config | sed -n ‘/CONFIG_ARM=/p‘ | wc -l )
ifeq ($(target_ARM),1)
SUBARCH = arm
endif
ARCH	 ?= $(SUBARCH)
SRCARCH := $(ARCH)

是读取了.config中的 CONFIG_ARM的值来确定的。

接下来就是加载 arch/arm/Kconfig 这个Kconfig文件了!

Kconfig文件是Kernel配置机制的核心所在,Kernel 的源代码里面含有很多个Kconfig文件,基本上每一层的目录里面都有,分别对应各个功能模块,各个Kconfig之间通过 source 命令加载。



四:关系

.config文件是最终的配置文件,通过make menuconfig命令调用了mconf  来解析出.config里面的值,因为要形成图形操作配置界面,那么就要加载每一个值的配置规则以及依赖关系,所以就需要加载Kconfig文件来对.config中的值在图形界面上进行配置和操作的规则!在图形界面上进行操作剪裁之后,可以保存到.config中去,同时mconf也会将结果生成到/include/generated/autoconf.h中,以供整个kernel使用,这个过程可以研究mconf.c的源代码。
这里对整个配置体系的大体结构分析学习了一下,后续学习config语言以及与makefile之间的关系!





撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/25147245