内核_.config 内核配置[ZT]--make menuconfig
来源:
ChinaUnix博客 作者: 发布时间:2008-04-25 06:25:34


随着 Linux 操作系统的广泛应用,特别是 Linux 在嵌入式领域的发展,越来越多的人开始投身到 Linux 内核级的研发中。面对日益庞大的 Linux 内核源代码,研发者在完成自己的内核代码后,都将面临着同样的问题,即怎样将源代码融入到 Linux 内核中,增加相应的 Linux 配置选项,并最终被编译进 Linux 内核。这就需要了解 Linux 的内核配置系统。
众所周知,Linux 内核是由分布在全球的 Linux 爱好者一起研发的,Linux 内核每天都面临着许多新的变化。但是,Linux 内核的组织并没有出现混乱的现象,反而显得很的简洁,而且具备很好的扩展性,研发人员能够很方便的向 Linux 内核中增加新的内容。原因之一就是 Linux 采用了模块化的内核配置系统,从而确保了内核的扩展性。
本文首先分析了 Linux 内核中的配置系统结构,然后,解释了 Makefile 和配置文档的格式连同配置语句的含义,最后,通过一个简单的例子--TEST Driver,具体说明怎样将自行研发的代码加入到 Linux 内核中。在下面的文章中,不可能解释任何的功能和命令,只对那些常用的进行解释,至于那些没有讨论到的,请读者参考后面的参考文献。
1. 配置系统的基本结构
Linux内核的配置系统由三个部分组成,分别是:
Makefile:分布在 Linux 内核源代码中的 Makefile,定义 Linux 内核的编译规则;
配置文档(config.in):给用户提供配置选择的功能;
配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图像界面连同基于 Xwindows 图像界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。
这些配置工具都是使用脚本语言,如 Tcl/TK、Perl 编写的(也包含一些用 C 编写的代码)。本文并不是对配置系统本身进行分析,而是介绍怎样使用配置系统。所以,除非是配置系统的维护者,一般的内核研发者无须了解他们的原理,只需要知道怎样编写 Makefile 和配置文档就能够。所以,在本文中,我们只对 Makefile 和配置文档进行讨论。另外,凡是涉及到和具体 CPU 体系结构相关的内容,我们都以 ARM 为例,这样不但能够将讨论的问题明确化,而且对内容本身不产生影响。
2. Makefile
2.1 Makefile 概述
Makefile 的作用是根据配置的情况,构造出需要编译的源文档列表,然后分别编译,并把目标代码链接到一起,最终形成 Linux 内核二进制文档。
由于 Linux 内核源代码是按照树形结构组织的,所以 Makefile 也被分布在目录树中。Linux 内核中的 Makefile 连同和 Makefile 直接相关的文档有:
Makefile:顶层 Makefile,是整个内核配置、编译的总体控制文档。
.config:内核配置文档,包含由用户选择的配置选项,用来存放内核配置后的结果(如 make config)。
arch/*/Makefile:位于各种 CPU 体系目录下的 Makefile,如 arch/arm/Makefile,是针对特定平台的 Makefile。
各个子目录下的 Makefile:比如 drivers/Makefile,负责所在子目录下源代码的管理。
Rules.make:规则文档,被任何的 Makefile 使用。
用户通过 make config 配置后,产生了 .config。顶层 Makefile 读入 .config 中的配置选择。顶层 Makefile 有两个主要的任务:产生 vmlinux 文档和内核模块(module)。为了达到此目的,顶层 Makefile 递归的进入到内核的各个子目录中,分别调用位于这些子目录中的 Makefile。至于到底进入哪些子目录,取决于内核的配置。在顶层 Makefile 中,有一句:include arch/$(ARCH)/Makefile,包含了特定 CPU 体系结构下的 Makefile,这个 Makefile 中包含了平台相关的信息。
位于各个子目录下的 Makefile 同样也根据 .config 给出的配置信息,构造出当前配置下需要的源文档列表,并在文档的最后有 include $(TOPDIR)/Rules.make。
Rules.make 文档起着很重要的作用,他定义了任何 Makefile 共用的编译规则。比如,假如需要将本目录下任何的 c 程式编译成汇编代码,需要在 Makefile 中有以下的编译规则:
%.s: %.c
$(CC) $(CFLAGS) -S $
给出本配置选项的名称, 对应配置变量, 对应配置帮助信息。在帮助信息中,首先简单描述此功能,其次说明选择了此功能后会有什么效果,不选择又有什么效果,最后,不要忘了写上"假如不清楚,选择 N(或)Y",给不知所措的用户以提示。
4. 实例
对于一个研发者来说,将自己研发的内核代码加入到 Linux 内核中,需要有三个步骤。首先确定把自己研发代码放入到内核的位置;其次,把自己研发的功能增加到 Linux 内核的配置选项中,使用户能够选择此功能;最后,构建子目录 Makefile,根据用户的选择,将相应的代码编译到最终生成的 Linux 内核中去。下面,我们就通过一个简单的例子--test driver,结合前面学到的知识,来说明怎样向 Linux 内核中增加新的功能。
4.1 目录结构
test driver 放置在 drivers/test/ 目录下:
$cd drivers/test
$tree
.
|-- Config.in
|-- Makefile
|-- cpu
| |-- Makefile
| `-- cpu.c
|-- test.c
|-- test_client.c
|-- test_ioctl.c
|-- test_proc.c
|-- test_queue.c
`-- test
|-- Makefile
`-- test.c
4.2 配置文档
1) drivers/test/Config.in
#
# TEST driver configuration
#
mainmenu_option next_comment
comment ’TEST Driver’
bool ’TEST support’ CONFIG_TEST
if [ "$CONFIG_TEST" = "y" ]; then
tristate ’TEST user-space interface’ CONFIG_TEST_USER
bool ’TEST CPU ’ CONFIG_TEST_CPU
fi
endmenu
由于 test driver 对于内核来说是新的功能,所以首先创建一个菜单 TEST Driver。然后,显示 "TEST support",等待用户选择;接下来判断用户是否选择了 TEST Driver,假如是(CONFIG_TEST=y),则进一步显示子功能:用户接口和 CPU 功能支持;由于用户接口功能能够被编译成内核模块,所以这里的询问语句使用了 tristate(因为 tristate 的取值范围包括 y、n 和 m,m 就是对应着模块)。
2) arch/arm/config.in
在文档的最后加入:source drivers/test/Config.in,将 TEST Driver 子功能的配置纳入到 Linux 内核的配置中。
4.3 Makefile
1)drivers/test/Makefile
# drivers/test/Makefile
#
# Makefile for the TEST.
#
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
ALL_SUB_DIRS := $(SUB_DIRS) cpu
L_TARGET := test.a
export-objs := test.o test_client.o
obj-$(CONFIG_TEST) += test.o test_queue.o test_client.o
obj-$(CONFIG_TEST_USER) += test_ioctl.o
obj-$(CONFIG_PROC_FS) += test_proc.o
subdir-$(CONFIG_TEST_CPU) += cpu
include $(TOPDIR)/Rules.make
clean:
for dir in $(ALL_SUB_DIRS); do make -C $$dir clean; done
rm -f *.[oa] .*.flags
drivers/test 目录下最终生成的目标文档是 test.a。在 test.c 和 test-client.c 中使用了 EXPORT_SYMBOL 输出符号,所以 test.o 和 test-client.o 位于 export-objs 列表中。然后,根据用户的选择(具体来说,就是配置变量的取值),构建各自对应的 obj-* 列表。由于 TEST Driver 中包一个子目录 cpu,当 CONFIG_TEST_CPU=y(即用户选择了此功能)时,需要将 cpu 目录加入到 subdir-y 列表中。
2)drivers/test/cpu/Makefile
# drivers/test/test/Makefile
#
# Makefile for the TEST CPU
#
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
ALL_SUB_DIRS := $(SUB_DIRS)
L_TARGET := test_cpu.a
obj-$(CONFIG_test_CPU) += cpu.o
include $(TOPDIR)/Rules.make
clean:
rm -f *.[oa] .*.flags
3)drivers/Makefile
……
subdir-$(CONFIG_TEST) += test
……
include $(TOPDIR)/Rules.make
在 drivers/Makefile 中加入 subdir-$(CONFIG_TEST)+= test,使得在用户选择 TEST Driver 功能后,内核编译时能够进入 test 目录。
4)Makefile
……
DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
DRIVERS-$(CONFIG_TEST) += drivers/test/test.a
DRIVERS-$(CONFIG_TEST_CPU) += drivers/test/cpu/test_cpu.a
DRIVERS := $(DRIVERS-y)
……
在顶层 Makefile 中加入 DRIVERS-$(CONFIG_TEST) += drivers/test/test.a 和 DRIVERS-$(CONFIG_TEST_CPU) += drivers/test/cpu/test_cpu.a。怎样用户选择了 TEST Driver,那么 CONFIG_TEST 和 CONFIG_TEST_CPU 都是 y,test.a 和 test_cpu.a 就都位于 DRIVERS-y 列表中,然后又被放置在 DRIVERS 列表中。在前面曾提到过,Linux 内核文档 vmlinux 的组成中包括 DRIVERS,所以 test.a 和 test_cpu.a 最终可被链接到 vmlinux 中。
参考资料
Document/kbuild/makefiles.txt,Linux Kernel Source code
Document/kbuild/config-language.txt,Linux Kernel Source code
Contributing to the Linux Kernel--The Linux Configuration System,Linux Journal,
http://www.linuxjournal.com/categories.php?op=newindex&
;catid=178
Unreliable Guide To Hacking The Linux Kernel,Paul Rusty Russell,rusty@rustcorp.com.au
关于作者
汤凯,通过 tangk73@hotmail.com能够跟他联系。
|
还没有关于此文章的相关评论!