learning
just as your
favourite thing
Linux
内核构建系统
(v1.0, 20 Nov 2010)
的前言
作为Linux 内核驱动程序开发者来说,虽说并不要求熟练掌握整个内核构建系统,而只是要求会写符合我们自己驱动程序需求的 Kbuild/Makefile 即可。但是,经常地,事情总是不会如我们所愿那样而一帆风顺的发展。
linux和安卓的关系倘若有一天你使用内核构建系统所提供的接口来编译驱动程序却不成功。那怎么办呢?看书、查资料和在mail list 上向别人请教固然可能解决问题,但是等问题解决了,那也可能是几天以后的事情了。
所以,这些方法对颇具探索精神的您来说,可能并非百分之百得完美和快截。 相反,您更喜欢或更习惯于直接去hacking 那些提供这些接口的内核代码,带着你的问题,以您目前所掌握的知识为基础去hacking ……就像本文所做的这样。
本文旨在重现数年前我对内核构建系统的hacking 过程,希望能对您嵌入式Linux 的学习有所启发。作为JulianTec 的建立者之一,我觉得或许JulianTec 没办法教会您所有的知识,但是在教您用什么样的方法去获得这些知识的方面,我相信她一定能对您有所帮助。
本文内容来自我在JulianTec 技术博客,具体的入口地址在 yihect.juliantec.info/julblog//post/4/17,所讨论的构建系统对应着 2.6.30 的内核版本。您可以到 中下载该版本的内核对照着阅读。
为了学习目的,任何人或组织都可以自由阅读本文档,但若您要在自己待发表的文章里面引用本文的内容,还请注名出处。提及上面的来源URL 或者JulianTec 都是可以接受的。
由于自身水平有限,再加上写时时间匆忙,本文中或许藏着这样或那样的错误。还请读者您能够指出,我将JulianTec 将努力确保文章质量。您可以发邮件到 yihct@juliantec.info JulianTec 。
Yihe Chen Nov 2010
目录
前言 (1)
目录 (3)
1. 概论 (4)
2. Linux内核构建系统所支持的目标 (6)
3. 构成内核构建系统的文件 (8)
3.1. 共有五大类文件 (8)
3.2. 内核构建系统中各文件之间的关系 (9)
4. 顶层Makefile的总体框架结构 (12)
4.1. 顶层Makefile如何处理混合目标 (14)
4.2. 顶层Makefile如何处理配置目标 (15)
4.3. 顶层Makefile如何处理构建目标及和.config无关目标 (19)
5. 用两个例子深入讨论如何处理构建目标 (25)
5.1. make ARCH=arm CROSS_COMPILE=arm-linux- (25)
5.1.1. 对目标 vmlinux 的处理 (26)
5.1.2. 对目标 modules 的处理 (49)
5.1.3. 对目标 zImage 的处理 (56)
5.2. make ARCH=arm CROSS_COMPILE=arm-linux- -C KERNELDIR M=dir (61)
5.2.1. 编译外部模块的先决条件 (61)
5.2.2. 如何实现这例子二中的外部模块构建 (62)
6. Linux内核构建系统如何处理单一目标 (66)
7. Linux内核构建系统对依赖关系的处理 (67)
1.概论
在xNIX世界中,您若要想使用任何一款软件,通常来说都必须先从官方站点上获取源代码、继而编译安装、最后才是动手使用。概括起来,整个其过程一般可分成以下几个步骤:
a)获取该软件的源代码;
源代码通常是以压缩包的形式由官方所发布出来的,所以到手后您必须解压。需要注意的是,如果官方代码中藏有bugs,而正好有热心人修正了这些bugs,并且发布出来一些补丁程序。那么您为了在后续使用时避免出现问题,您通常也需要下载这些补丁包,并进行patch操作。
b)进入到源代码目录中进行配置;
对大型的软件项目来说,配置必不可少。该步骤的目的之一是为了确定编译阶段需要使用到的各种工具和编译过程所面对的系统架构。比如编译器在哪里?连接器又使用哪一个?搞清楚在什么机器架构上进行编译,编译出来的程序又运行在什么架构上?其目的之二,您通常需要在配置过程中指定哪些功能特征是您所需要的。要知道,一个较大型的软件项目,其中的功能可为多种多样,而您,通常只需要其中的一小部分,所以您需要在下面编译之前指定出来。
c)编译该软件;
使用配置过程中所确定出来的工具,对实现您所指定那部分功能的代码模块进行编译,并经过连接,最后形成所需要的可执行程序或可执行映像。
d)安装部署所编译出来的结果
可执行程序的安装,就是要把他们放在PATH环境变量所指定的目录中去,通常是 /bin, /usr/bin, /sbin, /usr/sbin 之类的目录。那么可执行映像呢,这通常和嵌入式应用相关,您需要将这些映像下载到非易失性存贮器中,比如 EEPROM 或者 FLASH 中去。
当然,上面这个过程只是一般的过程。但是,像Windows平台那样,现在有很多软件也都发布了针对不同架构编译好的可执行应用程序包,为用户省却了烦琐的配置和编译,这种情况我们不去考虑。Linux内核作为一个大型的软件项目,其使用也遵循上面这样一个一般的过程。
针对Linux内核而言,上面的步骤b被称为kconfig,而步骤c即为kbuild。
kconfig时,我们要使用类似 "make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig" 的命令来选择我们所要的功能。这个命令结束时,我们所选择的结果会被记录到一个叫 ".config" 的隐藏文件中。注意,其中ARCH=arm规定了我们要为arm架构编译内核,而CROSS_COMPILE=arm-linux-规定了编
译内核时需要使用arm-linux-打头的交叉工具链。
.config文件生成后,我们就可以使用 "make ARCH=arm CROSS_COMPILE=arm-linux-" 之类的命令来做编译,即kbuild了。需要注意的是,对Linux内核做编译,其产生的可执行代码分布在两个部分中间:一个基本内核映像和数个可独立加载的模块。在使用Linux内核时,前者作为Linux操作系统的主体而常驻内存;而后者可按需要动态的加载到内存中或自内存中卸载,用以动态的修改内核所具有的功能。这种安排是作为整块式操作系统结构的Linux内核向微内核操作系统结构学习的结果。既然编译的出来的可执行代码可以以两种方
式存在,那么我们就必须预先告诉kbuild系统,哪部分放在基本内核里,哪部分又以模块的形式存在。所以显然,我们在配置过程中产生".config"文件的时候,除了需要记录我们所需要的功能外,还要记录这些功能都需要放在哪里。
Linux内核编译完成后,接下来要做的同样也是安装。对于x86等架构的桌面机来说,我们需要将基本内核映像放到文件系统中,通常是/boot目录下;对于嵌入式系统,我们要烧写进FLASH中。对于各种模块,我们也要装到文件系统的指定目录下面。另外值得一提的是为了让应用程序能正常使用C库,Linux内核还要向C库提供一套头文件,所以我们也需要将内核提供的头文件安装到文件系统相应的目录下面。安装可以手动进行,也可以自动的用类似 "make modinstd"、"make install"、"make headerinst"之类的命令。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论