Linux Kernel 实现了Kconfig和Kbuild以及Makefile,用于辅助内核的配置和编译,使得linux kernel的编译过程变得相当简单。
(一)内核编译
1、将Linux-3.5.4.tar.bz2解压至”/usr/src/kernel“目录下
cd /usr/src/kernels/
tar -jxvflinux-3.5.4.tar.bz2
说明一下:因为目标文件夹为当前目录,所以省略,负责的话应该在该指令后添加空格+目标文件夹的绝对路径;其次:-jxvflinux-3.5.4中间没有空格,该指令的意思就是将当前目录下的linux-3.5.4解压。如果你在执行该解压指令是没有执行上面的切换工作目录的指令,那么该指令应该为:
tar -jxvf压缩文件的路径 目标文件的路径
2、copy当前的内核配置文件作为心内核编译的配置文件
#cp /boot/config-3.3.4-5.fc17.i686.PAE /usr/src/kernels/linux-3.5.4/.config
3、将当前目录切换为/usr/src/kernels/linux-3.5.4/
4、安装一些编译过程中所需要依赖的库文件
#yum install ncurses-devel_* gcc* gcc_c++ *aclocal
5、make menuconfig
#make menucofig
生成编译阶段所需要的配置文件.config
6、 make all
该指令将生成内核ELF文件vmlinux,它对应于目标体系结构家的二进制内核映像文件。(x86体系结构下的bzImage 映像文件),make all指令将根据配置文件实现所有设备驱动模块以及可动态加载模块的编译。
7、make modules_install
安装模块到/lib/modules/linux-3.5.4
8、 make install
将vmlinuz-3.5.4,System.map-3.5.4 initramfs-3.5.4.img拷贝到/boot目录下并自动保存修改
9、重新启动,是否有3.5.4内核的加载项
(二)内核编译过程浅析
首先介绍内核编译过程中几个比较重要的概念:
1、Kconfig:Kconfig文件分布在Linux内核源码树的各个目录及其子目录中,最底层的Kconfig是“/arch/x86/Kconfig”,以该目录下的Kcofig文件为根,一层层使用source把需要加入各个目录中的Kconfig添加进来。Kconfig文件中设置了一些变量,用户通过设置变量的值来选择如何个性化自己的内核。
2、Makefile:分布在Linux内核源码树根目录以及各层子目录中,定义了Linux内核的编译规则。顶层的Mikefile文件采用递归的方式调用位于各个子目录中的Makefile文件。
在Linux内核中,有5种Makefile文件:
a、最顶层的Makefile文件
在内核编译的过程中,执行 “# make menuconfig”命令,顶层的Makefile会从读取最底层的Kconfig,从而递归调用各层的Kconfig配置文件,
生成最后编译内核所需要的.config文件。
b、内核的.config文件
在执行“# make menuconfig”之后生成的内核配置文件
c、arch/x86/Makefile文件
该文件提供补充体系结构的相关信息
d、Scripts目录下的Makefile文件
Scripts/Makefile.xxx定义了内核编译过程中的一些通用的规则
e、Kbuild Makefile文件
各级目录下的Makefile文件
那么,在内核编译的过程中这两种文件有什么作用呢?
在内核编译的过程中,Makefile会根据Kconfig文件中的定义来决定某个源文件该怎样被编译(编译成内核还是编译成模块),Makefile则定义了源码文件构建目标文件的规则。下面我们简单的举个例子:
在/drivers/myDriver下有如下的目录结构
|-Kconfig
|-Makefile
|-key
|--Kconfig
|--Makefile
|--key.c
|-test.c
首先在/drivers目录下:
Makefile文件中有如下语句:
obj-y +=myDriver ;编译过程包含子目录/drivers/myDrivers
Konfig文件中有如下语句。
source"drivers/MyDriver/Kconfig"
在drivers/MyDrivers/目录下也有Makefile以及Kconfig文件
Makefile:
obj_$(CONFIG_TEST)+=test.o
obj_y+=led
Kconfig:
menu "TEST MyDriver"
comment "Test MyDriver“
config TEST
tristate "MyDriver test"
source "/drivers/MyDrivers/key/Kcongig"
end menu
同样在~/.key目录下也有自己的Makefile以及Kconfig
Makefile
obj_$(CONFIG_LED)=led.o
Kconfig:
config LED
tristate "led support"
在执行#make menuconfig时,会出现如下菜单列表:
|-Test MyDriver
|--MyDriver test
|--led support
如果选中led support,那么执行#make menuconfig时,就会编译生成led.o文件。同时在.config文件中多出一行
CONFIG_TEST=m
那么在执行make命令时,顶层Makefile会调用.config文件进入MyDrivers/led子目录需找Makefile
obj_m +=led.o所以led.o被编绎成了模块。
说明一下:所有编译进内核的目标文件都存放在$(obj-y)列表中。build编译所有的$(obj-y)文件并调用”$(LD) -r“将他们合并到一个build_in.o文件中,稍后,该build_in.o文件会被其父Makefile文件链接进vmlinux中。vmlinux是linux源码未压缩的内核,是由arch/x86/head.o文件和arch/x86/kernel/init-task.o以及各个相关子目录下的built_in.o链接而成的。
接下来简单分析一下Linux内核编译过程
简单说来Linux Kernel的编译就是一个config再make的过程,make阶段会利用config阶段生成的一些配置文件。
a、“#make menuconfig”
第一步:顶层Makefile分析$(MAKECMDGOALS),判定只是一个config指令而不是build或者其他指令
第二步:menuconfig会匹配到Makefile中的“config %config”
在命令行输入“#make menuconfig”后,会显示MenuList,该list是由各个目录及其子目录的Kconfig文件组成的。
第三步:构建menuconfig目标
第四步:Script/Kconfig/mconf 读取arch/x86/Kconfig,并以此读入子Konfig文件,并将配置项的符号表建立起来。如果是第一次进行Linux内核的配置,尚没有.config文件,这些配置项的初始值在init/Kconfig文件中得到。mconf自上而下以此尝试,知道对应的文件存在,就将对应的文件作为默认的.config加载。
第五步:生成.config文件
手工完成配置之后,save设置,在源码的顶层目录下会生成一个.config文件,这个就是整个Kernel配置过程最重要的输出
总之,make menuconfig阶段最主要的作用就是用于生成内核编译所需要的.config文件。
b、“#make all”
顶层的Makefile文件,直接定位到目标:vmlinux和modules。Make会自动合并all的依赖项,并依次对依赖项进行构建。
那么在构建的过程是如何跟.config结合的呢?
在.config中的配置项的值将各个.o文件分为几个类别。如果配置项为y,那么对应的文件归为obj-y列表;如果为m,则对应的o文件归为obj-m列表,lib-y,lib-m等等。这样我们就可以通过调整配置项的值来选择是否将某功能编译到Linux Kernel中还是以Kernel module的形式存在。