使用menuconfig配置内核时对.config及内核模块的影响【使用的飞凌嵌入式板】
1.配置内核,默认的配置文件存放在linux-3.0.1\arch\arm\configs中,都是以“cpu名_defconfig”的形式命名。要添加一个默认的配置文件也很简单,只要将配置文件按上述形式命名放在这个configs目录下就可以了。通常我们不会直接使用make menuconfig重新制作整个linux-3.0.1\下的.config文件(即重新配置所有项,有10000多项呢),我们会先使用“make cpu名_defconfig”的形式生成默认的配置文件(即将该defconfig内容写入.config),或者直接使用“mv 厂家_config .config”的命令,用厂家提供的config直接覆盖.config,并在此基础上修改成我们需要的配置。【配置的结果就是在主目录下生成一个.config文件】
2.在menu界面下配置内核:
在menu界面的上方我们会看到这样一段说明:
Arrow keys navigate the menu. <Enter> selects submenus --->. │
│ Highlighted letters are hotkeys. Pressing <Y> includes, <N> excludes, │
│ <M> modularizes features. Press <Esc><Esc> to exit, <?> for Help, </> │
│ for Search. Legend: [*] built-in [ ] excluded <M> module < >
//-------------------------------------------------翻译--------------------------------------------------------------
用箭头键在menu中移动,回车键进入子菜单,高亮的字母是热键,按热键可以快速跳转,按Y包含选择项,按N去除选择项,按M增加模块化特征,按两次ESC退出当前菜单,按?键进入帮助界面,按/键搜索选项。[*]表示该内容被包含进内核,[]表示该内容不被包含进内核,[M]表示该内容以模块形式加载进内核。
这里我们看一下在.config中所做的配置,是如何影响最终生成的内核的。我们以DM9000网卡为例说明:
首先我们可以在生成的.config文件中看到有这样的内容CONFIG_DM9000=y
然后通过搜索主目录下的CONFIG_DM9000,有如下一些内容:
tanjiaqi@tanjiaqi-Vitual:~/Linux/linux-3.0.1$ grep "CONFIG_DM9000" * -nwR
arch/arm/mach-pxa/em-x270.c:200:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/arm/mach-pxa/colibri-pxa270.c:207:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/arm/mach-pxa/cm-x300.c:218:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/arm/mach-pxa/cm-x2xx.c:63:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/arm/mach-pxa/vpac270.c:385:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/arm/mach-s3c64xx/mach-smdk6410.c:153:#ifdef CONFIG_DM9000
arch/arm/mach-s3c64xx/mach-smdk6410.c:190:#endif //#ifdef CONFIG_DM9000
arch/arm/mach-s3c64xx/mach-smdk6410.c:643:#ifdef CONFIG_DM9000
arch/arm/configs/s3c2410_defconfig:244:CONFIG_DM9000=y
arch/arm/configs/smdk6410_defconfig:831:CONFIG_DM9000=y
arch/arm/configs/davinci_all_defconfig:71:CONFIG_DM9000=y
arch/arm/configs/trizeps4_defconfig:109:CONFIG_DM9000=y
arch/arm/configs/cm_x300_defconfig:68:CONFIG_DM9000=y
arch/arm/configs/mini2440_defconfig:121:CONFIG_DM9000=y
arch/arm/configs/colibri_pxa270_defconfig:90:CONFIG_DM9000=y
arch/arm/configs/mx1_defconfig:56:CONFIG_DM9000=y
arch/arm/configs/em_x270_defconfig:72:CONFIG_DM9000=y
arch/arm/configs/zeus_defconfig:72:CONFIG_DM9000=y
arch/arm/configs/at91sam9261_defconfig:62:CONFIG_DM9000=y
arch/arm/configs/cm_x2xx_defconfig:80:CONFIG_DM9000=y
arch/arm/mach-at91/board-sam9261ek.c:81:#if defined(CONFIG_DM9000)
arch/arm/mach-at91/board-sam9261ek.c:152:#endif /* CONFIG_DM9000 */
arch/blackfin/mach-bf527/boards/cm_bf527.c:251:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf527/boards/cm_bf527.c:927:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf527/boards/ezkit.c:345:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf527/boards/ezkit.c:1211:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf537/boards/stamp.c:182:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf537/boards/stamp.c:2791:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf533/boards/ip0x.c:35:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf533/boards/ip0x.c:263:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf533/boards/H8606.c:42: #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/mach-bf533/boards/H8606.c:411:#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
arch/blackfin/configs/IP0X_defconfig:61:CONFIG_DM9000=y
arch/blackfin/configs/H8606_defconfig:52:CONFIG_DM9000=y
drivers/net/Makefile:256:obj-$(CONFIG_DM9000) += dm9000.o
FORLINX6410_CFG:831:CONFIG_DM9000=y//我们使用的是飞凌提供的板卡,很明显//这个就是厂家提供给我们的配置文件
include/generated/autoconf.h:517:#define CONFIG_DM9000 1
include/config/auto.conf:517:CONFIG_DM9000=y
include/config/tristate.conf:196:CONFIG_DM9000=Y
从上面我们可以看出,配置项CONFIG_DM9000出现在以下一些文件中:
①arm架构的源文件中
②configs目录下的默认配置文件或厂家配置文件中
③驱动文件夹子目录下的makefile中
④include/generated/autoconf.h中
⑤include/config/auto.conf中
显然arm架构的源文件中出现的宏CONFIG_DM9000的定义来源于include/generated/autoconf.h文件,其实在.config中配置的所有m和y属性的选项,在include/generated/autoconf.h中都会以宏定义的形式出现,且宏的值都被定义为1,这个autoconf.h文件是根据.config中的配置自动生成的。既然在autoconf.h文件中我们无法区分
m和y属性,那么我们就需要在子目录下的makefile中区分,在makefile文件中,我们有
obj-$(CONFIG_DM9000) += dm9000.o,替换掉makefile中的变量引用,根据配置的不同,有obj-y += dm9000.o和obj-m += dm9000.o两种情况【如果CONFIG_DM9000没有定义,则为空,会出现obj- += dm9000.o,
makefile并不会处理变量obj-】,而obj-y最终会以dm9000.o的形式编译到内核里面去,而obj-m的内容最终则会编译成dm9000.ko作为模块加载到内核当中。而对于子目录makefile中的变量CONFIG_DM9000则是由auto.conf中定义,而auto.conf文件则是由.config中的配置生成,此外,auto.conf会被顶层的makefile包含来影响内核的生成。
因此,综上所述,根据.config配置会自动生成autoconf.h和auto.conf两个文件,autoconf.h会被所有的源代码调用,而auto.conf则被所有的Makefile使用。
3.Linux内核的Makefile分析,如果想对linux内核的Makefile有个比较全面的了解,建议阅读一下linux-3.0.1\Documentation\kbuild\makefiles.txt【中文版本翻译】
我们先讲解一下子目录下面的Makefile,这里我就以/linux-3.0.1/drivers下的Makefile为起始,来简单介绍一下各个目录下Makefile的构成(具体语法我们就不展开来讲了,请自行去阅读上面的英文介绍或者中文翻译)。
在/linux-3.0.1/drivers下的Makefile中有:
obj-y += gpio/ //这种是表示将访问当前目录下的gpio目录,并根据
//配置在gpio目录下的Makefile中选择内容添加到内核
而在linux-3.0.1/drivers/gpio中的Makefile里有:
obj-$(CONFIG_GPIOLIB) += gpiolib.o //表示我们会根据CONFIG_GPIOLIB变量的值
//选择不同的编译方式:
//y:编译进内核(.o) m:编译成模块(.ko)
此外,如果有复合文件,在老版本中,会以如下形式编译进内核,
obj-y += gpio.o //即gpio.o将被编译到内核中,但它又是由
gpio-objs := a.o b.o //a.o ,b.o生成
在新版本的linux中,做法如下:
obj-y += isdn.o
isdn-y := isdn_net_lib.o isdn_v110.o isdn_common.o
接下来我们直接分析顶层目录下的Makefile,依次展开来理清linux内核源码包的结构。
顶层目录下Makefile中有:
ARCH ?= arm
drivers-y := drivers/ sound/ firmware/
-include include/config/auto.conf //由.config生成
all: vmlinux //顶层Makefile的第一个目标
//…
include $(srctree)/arch/$(SRCARCH)/Makefile //包含了架构的Makefile
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
init-y := $(patsubst %/, %/built-in.o, $(init-y)) //init-y = init/ built-in.o
core-y := $(patsubst %/, %/built-in.o, $(core-y)) // core-y= usr/ built-in.o
// kernel/ built-in.o
//mm built-in.o
//fs/ built-in.o
// ipc/ built-in.o
// security/ built-in.o
// crypto/ built-in.o
// block/ built-in.o
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) // drivers-y= drivers/ built-in.o
// sound/ built-in.o
// firmware/ built-in.o
net-y := $(patsubst %/, %/built-in.o, $(net-y)) // net-y= net/ built-in.o
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2) // libs-y= lib/ lib.a lib/ built-in.o
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
ifdef CONFIG_SAMPLES
$(Q)$(MAKE) $(build)=samples
endif
ifdef CONFIG_BUILD_DOCSRC
$(Q)$(MAKE) $(build)=Documentation
endif
$(call vmlinux-modpost)
$(call if_changed_rule,vmlinux__)
$(Q)rm -f .old_version
在arch/arm/Makefile中有:
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
在链接生成vmlinux时,我们使用的链接脚本是/linux-3.0.1/arch/arm/kernel/vmlinux.lds,但是在未经make的linux源码包中我们找不到这样一个文件,只能找到/linux-3.0.1/arch/arm/kernel/vmlinux.lds.S文件,显然前面那个链接脚本就是根据这个文件生成的。