分类: LINUX
2009-12-25 09:33:58
对于一个开发者来说,将自己开发的内核代码加入到Linux内核中,需要有3个步骤。
(1)确定把自己开发代码放入到内核的位置。
(2)把自己开发的功能增加到Linux内核的配置选项中,使用户能够选择此功能。
(3)构建子目录Makefile,根据用户的选择,将相应的代码编译到最终生成的Linux内核中去。
本节介绍Linux内核所支持的6种配置方式,并重点讨论常用的make menuconfig的用法。
Linux内核主要支持以下6种配置方式。
n make config:基于命令行的问答方式,通过执行make config开始,使用scripts/ Configure脚本解释工具去执行脚本。它针对每一个内核配置选项会有一个提问,回答y则选中,回答n则去掉,一旦选错一个就必须从头再来,故不建议使用此种方式。
n make oldconfig:也是通过命令行的方式,但它要求手动设定在. config中没有设定的选项,而make config则不管在.config中是否设定过都要求用户重新设定。这是一个非互动性的脚本,用系统当前内核的设置作为配置标准,重新编译新内核。适用于只进行简单升级的情况。
n make menuconfig:采用菜单方式进行配置,如图2-6所示。用户可以在Linux主机或网络中的某个工作站进行操作。该方法使用scripts/Menuconfig脚本解释工具去执行脚本。执行make menuconfig命令以后,会出现一个以curses为基础的、终端式的配置菜单,通过该菜单可以很方便地进行内核的配置。如果.config文件存在,则会根据该文件来设定默认值。一般情况下我们会选择该方法进行配置。
图2-6 make menuconfig
n make xconfig:也是采用菜单方式进行配置的,如图2-7所示。但必须在Linux主机上执行。make xconfig显示以Qt为基础的X Windows配置菜单,在GUI下配置内核,感觉很直观和清晰。同样,如果.config文件存在,则会根据该文件来设定默认值。
图2-7 make xconfig
n make gconfig:类似make xconfig,不同的是,它是以GTK为基础的GUI环境。
n make defconfig:能够根据机器的类型对内核进行默认的配置,免去了动手配置的麻烦。但经过测试,它很难配置出一个功能比较完善的内核,尤其是对于非Intel CPU的识别、优盘的支持、NTFS分区的支持以及ADSL的使用等问题做的还不是很令人满意。
显然,这6种方式的实质是相同的,不管选择哪种方法,在对Linux内核配置选项进行选择设定后,都会在内核顶层目录下生成一个隐藏的.config文件,它包含了所有配置选项的用户选择信息。当下一次make menuconfig时,会生成一个新的.config文件,原来的文件被更名为.config.old。
通常使用make menuconfig方式进行配置,这种方式简单明了,受条件制约小。执行如下命令:
#make menuconfg
系统会出现如图2-6所示的菜单方式,将内核的可配置选项呈现给用户。
每一个莱单项按模块功能分类,下面包含若干具体子项。例如Processor type and features (中央处理器类型及特性)选项就包含以下子项,如图2-8所示。
用户只需要根据自身特定系统的应用需求,对相应的功能模块进行取舍,当用户需要添加某项功能时,将光标移动到该位置,按空格键选中该项功能,此时选项左端的括号内出现“*”表示选择有效,再按空格键时,可以取消该项的选择。当用户在根据自己的系统需求配置好内核,退出配置菜单时,需要保存修改后的内核配置。
图2-8 Processor type and features(中央处理器类型及特性)选项
若用户选择不保存,则进行的所有配置操作无效,内核配置仍然为原来的状态,若选择保存,系统会在当前目录下生成一个.config文件,其后要进行的内核编译就是根据这个.config文件来进行条件编译以生成相应的可执行文件的。
Linux 2.4内核配置文件为config.in,Linux 2.6内核配置文件为Kconfig,二者大同小异,本节将介绍config.in的配置方法。
该文件被顶层Makefile包含,Rules.make及子目录中的Makefile并未包含这个文件,它是通过在顶层Makefile中设置并出口(export)变量MAKEFILES来向下传递的,比如MAKEFILES = $(TDPDIR)/.config。.config文件包括以下两个文件。
n arc/aim/config.in文件:在配置完成后会生成.config文件,其内容为相应的宏定义。该文件提供了总体的内核配置菜单选项,包括运行make menuconfig等命令出现的菜单。具体的子配置菜单选项需在其他各级子目录下的config.in(在2.4内核中脚本为各级目录下的config.in,而在2.6内核中变为Kconfig)中描述。当用户开发了新功能程序并需将其相关的配置选项加入到Linux的配置菜单中,以供用户需要此功能时进行选择,这时要在各级目录下的config.in文件中用配置语言来编写相应的配置脚本。config具体语法请参考Documentation/kbuild/CONFIG_ language.txt。
n include/Linux/autoconf.h:同.config一样,该文件也是在make menuconfig后产生的,它是根据内核配置情况由一些预处理语句组成。
几乎所有的源文件都会通过#include < Linux/config. h>来嵌入autoconf. h文件。当配置选项发生变化时,会更新autoconf. h,如果按照通常方法,使用make dep在每个子目录下生成依赖文件.depend,将造成所有源代码的重新编译。为了优化Make过程,减少不必要的重新编译,Linux开发了专用的mkdep及split-include工具。在script目录下有工具mkdep用来取代make dep来生成 .depend文件,它在处理源文件时,将忽略Linux/config.h头文件,直接查找源文件中具有“CDNFIG_”特征的宏定义。例如,如果有这样的行:
#ifdef CONFIG_PCI
它就会在depend文件中输出$(wildcard/opt/Linux/include/contig/pci.h),split-include工具以auto-conf.h为输入文件,利用autoconf.h中的“CONFIG_”标记,生成与mkdep相对应的文件。例如,如果autoconf.h中有#undef CONFIG_PCI这样的行,它就会生成include/ config/pci.h文件,其内容只有一行:
#undef CONFIG_PCI
表示不支持PCI设备。include/config/下的文件名只在.depend文件中出现,内核源文件是不会嵌入它们的。这样的话,每重新配置一次内核,就会运行工具split-include,依次来检查旧的子文件的内容,以确定是否需要更新它们。这样,不管autoconf.h修改日期如何,只要其配置不变,make就不会重新编译内核。
Kconfig文件是Linux 2.6.x系统的主要构成部分,它作为内核配置文件,主要包含可供用户选择的配置选项,配置程序将根据这些内容来显示相关配置选项,并将配置后生成的选项信息存放在.config文件中。
下面我们将从一个内核中的Kconfig文件来讲述Kconfig的格式含义,当然,由于篇幅限制,我们删掉了大部分重复的内容,只保留了一些典型的结构:
#
# Network configuration
#
menu "Networking support"
config PACKET
tristate "Packet socket"
---help---
The Packet protocol is used by applications which communicate directly with
network devices without an intermediate network protocol implemented in
the kernel,e. g. tcpdump.
If you want them to work,choose Y.
To compile this driver as a module,choose M here:the module will be called
af_packet.
If unsure,say Y.
config PACKET_MMAP
bool "Packet socket:mmapped IO"
depends on PACKET
---help---
If you say Y here,the Packet protocol driver will use an IO mechanism that
results in faster communication.
If unsure,say N.
config UNIX
tristate "Unix domain sockets"
---help---
If you say Y here,you will include support for Unix domain sockets; sockets
are the standard Unix mechanism for establishing and accessing network
connections. Many commonly used programs such as the X Window system and
syslog use these sockets even if your machine is not connected to any
network. Unless you are working on an embedded system or something
similar,you therefore definitely want to say Y here.
To compile this driver as a module,chaise M here; the module will be called
unix. Note that several important services won't work correctly if you
say M here and then neglect to load the module.
Say Y unless you know what you are doing.
source "net/sched/Kconfig"
source "drivers / net / Kconfig"
source "net/ bluetooth / Kconfig"
endmenu
说明如下:
n 在上面的文件中,符号#后面的内容为注释,不起任何作用。
n menu作为一个Kconfig文件的主要选项,后面跟随的字符串,用引号括起来,用做一个配置选项的选项名。一般一个Kconfig文件中也可以有多个menu。menu可以嵌套使用,endmenu表示一个menu的结束。
n 一个menu可以有多个config,每个config作为一个子项,又包含了几个部分。
n 内核源码的每个文件夹下都包含Kconfig文件,父目录下的Kconfig文件使用source "net/bluetooth/Kconfig"来包含子目录下的Kconfig文件,而最终的顶部的Kconiig文件则由scripts/kconfig/中的文件构成,所有的这些,组成了一个Kconfig树。
n config子项中包含了几个小的部分,其中config子项后面跟随的字符串用于配置完成后,如果该选项被选中,则该字符串前面加上CONFIG_后缀,作为一个宏,写入配置结果.config中。
n tristate用于config的选项类别,有-boot、tristate、string、hex、integer这几种可能,一般常用tristate,tristate的意思是三态,即可以是我们上面介绍的未选中——不编译、选中——编译为模块、选中——编译为新操作系统的一部分3种状态,驱动一般使用这个类别。
n 在config的选项类别tristate后,跟随一个用引号括起来的字符串,实际是以下代码的缩写:
tristate
prompt "something support"
而prompt "something support"字符串的作用是,作为一个config名字,在配置程序中显示出来,如果该config对应的名字被选中,则该config被选中。
n depends on的意义是本config依赖于另外一个config,如果想选择本选项,需要先选中本选项依赖的那个选项。
n help选项的意思就是一些说明该config的资料,这样在配置新内核的时候,配置人员可以从这里知道config的内核模块是什么作用,是否需要选入新的操作系统中。
Linux内核中提供了很多设备的驱动代码,但在每个项目中总会需要添加我们自己的驱动,比如我们需要添加LED的驱动。我们可以先独立去编写和调试这个驱动,等成熟后应该放到内核目录树中,使用make modules命令统一编译。而且要在配置选项中体现出来,用户可以使用make menuconfig命令去配置编译。假设驱动代码已编写、调试完毕,下面我们就以添加LED驱动为例来讲解Kconfig文件的配置方法。
(1)选择一个放置驱动代码的位置:
cd drivers
mkdir led
把写好的代码(假定为LED.c)放到这个drivers/led目录中。
(2)drivers/led添加Kconfig文件,内容如下:
menu "Led support"
config LED
tristate "LED support"
---help---
LED use gpio as ir input .
If you want LED support,you should say Y here and also to the
specific driver for your bus adapter(s) below.
This led support can be built as a module.
endmenu
(3)在drivers/led添加Makefile文件,编写Makefile:
obj-$(CONFIG_LED) += LED.o
(4)修改上一级Makefile和Kconfig。
在Makefile中添加:
obj-$(CONFIG_LED) += led/
在Kconfig中添加:
source "drivers/led/Kconfig"
(5)最后,在arch/arm的Kconfig中添加:
source "drivers/led/Kconfig"
具体位置视平台架构而定。
这样,Kconfig文件就修改完成了。此时可以使用make menuconfig,发现已有LED support--->选项,进入后选择M,再使用make modules,就可以发现在led目录下已生成了LED.ko。