第 7 章 配置编译内核
7.2 配置编译内核源码
7.2.2 内核配置系统
Linux 内核源代码支持二十多种体系结构的处理器,还有各种各样的驱动程序等选项。
因此,在编译之前必须根据特定平台配置内核源代码。Linux 内核有上千个配置选项,配置 相当复杂。所以,Linux 内核源代码组织了一个配置系统。
Linux 内核配置系统可以生成内核配置菜单,方便内核配置。配置系统主要包含 Makefile、
Kconfig 和配置工具,可以生成配置界面。配置界面是通过工具来生成的,工具通过 Makefile 编译执行,选项则是通过各级目录的 Kconfig 文件定义。
Linux 内核配置命令有:make config、make menuconfig 和 make xconfig。分别是字符界 面、ncurses 光标菜单和 X-window 图形窗口的配置界面。字符界面配置方式需要回答每一个 选项提示,逐个回答内核上千个选项几乎是行不通的;图形窗口的配置界面很好,光标菜单 也方便实用。例如执行 make xconfig,主菜单界面如图 7.1 所示。
tyw藏书
图 7.1 内核图形配置界面
那么这个配置界面到底是如何生成的呢?这里结合配置系统的 3 个部分分析一下。
1.Makefile
Linux 内核的配置编译都是由顶层目录的 Makefile 整体管理的。顶层目录的 Makefile 定 义了配置和编译的规则。关于 Makefile 的具体使用方法可以参考第 3 章的内容,这里重点分 析相关的变量和规则。
参考内核源码包中的 Documentation/kbuild/makefiles.txt,可以得到内核使用 Makefile 的 详细说明。
在顶层的 Makefile 中,可以查找到如下几行定义的规则。
config %config: scripts_basic outputmakefile FORCE $(Q)mkdir -p include/linux
$(Q)$(MAKE) $(build)=scripts/kconfig $@
这就是生成内核配置界面的命令规则,它也定义了执行的目标和依赖的前提条件,还有 要执行的命令。
这条规则定义的目标为 config %config,通配符%意味着可以包括 config、xconfig、gconfig、
menuconfig 和 oldconfig 等。依赖的前提条件是 scripts_basic outputmakefile,这些在 Makefile 也是规则定义,主要用来编译生成配置工具。
那么这条规则执行的命令就是执行 scripts/kconfig/Makefile 指定的规则。相当于:
tyw藏书
make -C scripts/kconfig/ config 或者
make -C scripts/kconfig/ %config
这两行命令是使用配置工具解析 arch/$(ARCH)/Kconfig 文件,生成内核配置菜单。
$(ARCH)变量是 Linux 体系结构定义,对应 arch 目录下子目录的名称。Kconfig 包含了内核 配置菜单的内容,那么 arch/$(ARCH)/Kconfig 是配置主菜单的文件,调用管理其他各级 Kconfig。
根据配置工具的不同,内核也有不同的配置方式。有命令行方式,还有图形界面方式。
表 7.2 是各种内核配置方式的说明。
表7.2 内核配置方式说明
配 置 方 式 功 能
config 通过命令行程序更新当前配置
menuconfig 通过菜单程序更新当前配置
xconfig 通过 QT 图形界面更新当前配置
gconfig 通过 GTK 图形界面更新当前配置
oldconfig 通过已经提供的.config 文件更新当前配置
randconfig 对所有的选项随机配置
defconfig 对所有选项使用缺省配置
allmodconfig 对所有选项尽可能选择“m”
allyesconfig 对所有选项尽可能选择“y”
allnoconfig 对所有选项尽可能选择“n”的最小配置
这些内核配置方式是在 scripts/kconfig/Makefile 中通过规则定义的。从这个 Makefile 中,
可以找到下面一些规则定义。如果把变量或者通配符带进去,就可以明白要执行的操作。这 里的 ARCH 以 arm 为例来说明。
xconfig: $(obj)/qconf
$< arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/qconf arch/arm/Kconfig
使用 QT 图形库,生成内核配置界面。arch/arm/Kconfig 是菜单的主配置文件,每种配置 方式都需要。
gconfig: $(obj)/gconf
$< arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/gconf arch/arm/Kconfig 使用 GTK 图形库,生成内核配置界面。
tyw藏书
menuconfig: $(obj)/mconf
$(Q)$(MAKE) $(build)=scripts/lxdialog $< arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/mconf arch/arm/Kconfig 使用 lxdialog 工具,生成光标配置菜单。
因为 mconf 调用 lxdialog 工具,所以需要先编译 scripts/lxdialog 目录。
config: $(obj)/conf
$< arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/conf arch/arm/Kconfig 完全命令行的内核配置方式。
oldconfig: $(obj)/conf
$< -o arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/conf -o arch/arm/Kconfig
完全命令行的内核配置方式。使用“-o”选项,直接读取已经存在的.config 文件,要求 确认内核新的配置项。
silentoldconfig: $(obj)/conf $< -s arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/conf -s arch/arm/Kconfig
完全命令行的内核配置方式。使用“-s”选项,直接读取已经存在的.config 文件,提示 但不要求确认内核新的配置项。
%_defconfig: $(obj)/conf
$(Q)$< -D arch/$(ARCH)/configs/$@ arch/$(ARCH)/Kconfig
执行命令:scripts/kconfig/conf -D arch/arm/configs/%_defconfig arch/arm/Kconfig
完全命令行的内核配置方式。读取缺省的配置文件 arch/arm/configs/%_defconfig,另存 成.config 文件。
通过上述各种都可以完成配置内核的工作,在顶层目录下生成.config 文件。这个.config 文件保存大量的内核配置项,.config 会自动转换成 include/linux/autoconf.h 头文件。在 include/linux/config.h 文件中,将包含使用 include/linux/autoconf.h 头文件。
2.配置工具
不同的内核配置方式,分别通过不同的配置工具来完成。scripts 目录下提供了各种内核 配置工具,表 7.3 是这些工具的说明。
表 7.3 内核配置工具说明
配 置 工 具 Makefile 相关目标 依赖的程序和软件
tyw藏书
conf defconfig oldconfig … conf.c zconf.tab.c mconf menuconfig mconf.c zconf.tab.c
调用 scripts/lxdialog/lxdialog qconf xconfig qconf.c kconfig_load.c zconf.tab.c
基于 QT 软件包实现图形界面 gconf gconfig gconf.c kconfig_load.c zconf.tab.c
基于 GTK 软件包实现图形界面
其中 zconf.tab.c 程序实现了解析 Kconfig 文件和内核配置主要函数。zconf.tab.c 程序还直 接包含了下列一些 C 程序,这样各种配置功能都包含在 zconf.tab.o 目标文件中了。
#include "lex.zconf.c" //lex 语法解析器
#include "util.c" //配置工具
#include "confdata.c" //.config 等相关数据文件保存
#include "expr.c" //表达式函数
#include "symbol.c" //变量符号处理函数
#include "menu.c" //菜单控制函数
理解这些工具的使用,可以更加方便地配置内核。至于这些工具的源代码实现,一般没 有必要去详细分析。
3.Kconfig
Kconfig 文件是 Linux 2.6 内核引入的配置文件,是内核配置选项的源文件。内核源码中 的 Documentation/kbuild/kconfig-language.txt 文档有详细说明。
前面已经提到了 arch/$(ARCH)/Kconfig 文件,这是主 Kconfig 文件,跟体系结构有关系。
主 Kconfig 文件调用其他目录的 Kconfig 文件,其他的 Kconfig 文件又调用各级子目录的配置 文件,成树状关系。
菜单按照树状结构组织,主菜单下有子菜单,子菜单还有子菜单或者配置选项。每个选 项可以有依赖关系,这些依赖关系用于确定它是否显示。只有被依赖项父项已经选中,子项 才会显示。
下面解释一下 Kconfig 的特点和语法。
(1)菜单项
多数选项定义一个配置选项,其他选项起辅助组织作用。举例说明单个的配置选项 的定义。
config MODVERSIONS
bool "Set version information on all module symbols"
depends MODULES help
Usually, modules have to be recompiled whenever you switch to a new kernel. ...
tyw藏书
每一行开头用关键字“config”,后面可以跟多行。后面的几行定义这个配置选项的属性。
属性包括配置选项的类型、选择提示、依赖关系、帮助文档和缺省值。同名的选项可以重复 定义多次,但是每次定义只有一个选择提示并且类型不冲突。
(2)菜单属性
一个菜单选项可以有多种属性,不过这些属性也不是任意用的,受到语法的限制。
每个配置选项必须有类型定义。类型定义包括:bool、tristate、string、hex、int 共 5 种。
其中有 2 种基本的类型:tristate 和 string,每种类型定义可以有一个选择提示。表 7.4 说明了 菜单的各种属性。
表7.4 内核菜单属性说明
属 性 语 法 说 明
选择提示 "prompt" <prompt>
["if" <expr>]
每个菜单选项最多有一条提示,可以显示在菜单上。某选择提示可选 的依赖关系可以通过“if”语句添加
缺省值 "default" <expr> ["if"
<expr>]
on"/"requires" <expr>
这个定义了菜单选项的依赖关系。如果定义多个依赖关系,那么要用
“&&”符号连接。依赖关系对于本菜单项中其他所有选项有效(也可 以用“if”语句)
反向依赖 "select" <symbol>
["if" <expr>]
普通的依赖关系是缩小符号的上限,反向依赖关系则是符号的下限。
当前菜单符号的值用作符号可以设置的最小值。如果符号值被选择了 多次,这个限制将被设成最大选择值。反向依赖只能用于布尔或者三 态符号
数字范围
"range" <symbol>
<symbol> ["if"
<expr>]
<expr> ::= <symbol> 把符号转换成表达式,布尔和三态符号可以转换成对应的表达式值。其他类 型符号的结果都是“n”
<symbol> '=' <symbol> 如果两个符号的值相等,返回“y”,否则返回“n”
续表
tyw藏书
表 达 式 结 果 说 明
<symbol> '!=' <symbol> 如果两个符号的值相等,返回“n”,否则返回“y”
'(' <expr> ')' 返回表达式的值,括号内表达式优先计算 '!' <expr> 返回(2-/expr/)的计算结果
<expr> '&&' <expr> 返回 min(/expr/, /expr/)的计算结果
<expr> '||' <expr> 返回 max(/expr/, /expr/)的计算结果
一个表达式的值是“n”、“m”或者“y”(或者对应数值的 0、1、2)。当表达式的值为
“m”或者“y”时,菜单选项变为显示状态。
符号类型分为两种:常量和非常量符号。
非常量符号最常见,可以通过 config 语句来定义。非常量符号完全由数字符号或者下划 线组成。
常量符号只是表达式的一部分。常量符号总是包含在引号范围内的。在引号中,可以使 用其他字符,引号要通过“\”号转义。
(4)菜单组织结构
菜单选项的树状结构有两种组织方式。
第一种是显式的声明为菜单。
menu "Network device support"
depends NET config NETDEVICES ...
endmenu
“menu”与“endmenu”之间的部分成为“Network device support”的子菜单。所有子选 项继承这菜单的依赖关系,例如,依赖关系“NET”就被添加到“NETDEVICES”配置选项 的依赖关系列表中。
第二种是通过依赖关系确定菜单的结构。
如果一个菜单选项依赖于前一个选项,它就是一个子菜单。这要求前一个选项和子选项 同步地显示或者不显示。
config MODULES
bool "Enable loadable module support"
config MODVERSIONS
bool "Set version information on all module symbols"
depends MODULES
comment "module support disabled"
depends !MODULES
MODVERSIONS 依赖于 MODULES,这样只有 MODULES 不是“n”的时候,才显示。
反之,MODULES 是“n”的时候,总是显示注释“module support disabled”。
tyw藏书
(5)Kconfig 语法
Kconfig 配置文件描述了一系列的菜单选项。每一行都用一个关键字开头(help 文字例外)。 菜单的关键字见表 7.6 所示。其中菜单开头的关键字有:config、menuconfig、choice/endchoice、
comment、menu/endmenu。它们也可以结束一个菜单选项,另外还有 if/endif、source 也可以 结束菜单选项。
表7.6 Kconfig 菜单关键字说明
关 键 字 语 法 说 明
config "config" <symbol>
<config options>
这可以定义一个配置符号<symbol>,并且可以配置选项 属性
menuconfig "menuconfig" <symbol>
<config options>
这类似于简单的配置选项,但是它暗示:所有的子选项
这类似于简单的配置选项,但是它暗示:所有的子选项