Linux内核学习之编译篇
Linux内核发展至今,文件数已经接近6万,代码量相当巨大。这一方面是内核功能不断增强补充的原因,另一方面当然是Linux的兼容性考虑,导致整个工程非常浩荡,而且很多文件名都一样,处于不同目录而已,这样一来,读者在学习阅读时就容易困惑,到底那个文件才是我需要的呢?这就涉及到本篇要谈到的问题。当然本文不只是告诉你怎么找文件,更主要是谈谈编译方面的机制。
了解Makefile
Kconfig概述
Linux Makefile
了解Makefile
关于Makefile的语法,基本规则很简单,就是告诉make程序你的工程结构,你所需要编译的目标,以及目标又依赖于什么文件生成。最简单的makfile只要有这几个基本要素就够了。比如Linux 根目录下的Makefile中的一个规则如下:
config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
含义:config是编译目标,依赖于3个文件(或伪目标):scripts_basic outputmakefile FORCE,而接下来的一行以TAB键开始(必须如此),就是针对这个目标所要执行的命令,这个命令是Linux环境下可执行的程序或shell脚本。
更加具体的语法,我强烈推荐阅读陈皓的文章:跟我一起写Makefile
Kconfig概述
这又是什么东西?其实我很想直接就开始分析Linux Makefile的内容,但是Linux这个系统的配置比较复杂,又绕不开这个。本节主要简要介绍其作用,而具体的语法不打算详述。可以参考linux工程目录下的文档:Documentation\kbuild\kconfig-language.txt,英文偏弱的,就去度娘搜一些中文材料看看。学习时最好结合配置界面和Kconfig文件,对照着看。
我所用的版本为4.1.6,具体的版本可以用任意ftp软件连接ftp.kernel.org获取,或者直接登录kernel网页版。
OK,我们随便打开一个Linux子目录的Makefile来大概了解一下,比如mm目录下的Makefile部分内容:
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o
obj-$(CONFIG_FRONTSWAP) += frontswap.o
obj-$(CONFIG_ZSWAP) += zswap.o
obj-$(CONFIG_HAS_DMA) += dmapool.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
以上你会看到有很多CONFIG_
开头的宏,这个哪里来的?别急,打开同一个目录下的Kconfig文件,截取部分如下:
config FRONTSWAP
bool "Enable frontswap to cache swap pages if tmem is present"
depends on SWAP
default n
help
Frontswap is so named because it can be thought of as the opposite
of a "backing" store for a swap device. The data is stored into
"transcendent memory", memory that is not directly accessible or
addressable by the kernel and is of unknown and possibly
time-varying size. When space in transcendent memory is available,
a significant swap I/O reduction may be achieved. When none is
available, all frontswap calls are reduced to a single pointer-
compare-against-NULL resulting in a negligible performance hit
and swap data is stored as normal on the matching swap device.
If unsure, say Y to enable frontswap.
Now,你看到了”config FRONTSWAP“,这个配置项最终会构成”CONFIG_FRONTSWAP“,其值可以为n或y。这样就和前面提到的obj-$(CONFIG_FRONTSWAP)匹配上了,y表示obj-y指定的文件会最终编译进内核,n表示obj-n指定的文件不参与编译。看到这里,我希望你明白Kconfig里面的配置项和最终的宏的关系,也就是会自动添加上”CONFIG_“。
接下来,我们就应该要知道怎么来配置这些宏了,最一般的方式,我们通过在根目录下面执行如下命令来手动配置:
weimh1@weimh1-ubuntu:~/work/sourcecode/linux-4.1.6$ make menuconfig
这个编译目标(menuconfig)对应于根Makefile中的这条规则:
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
上面编译命令最终又会进入scripts/kconfig 中的Makefile执行这个目标:
menuconfig: $(obj)/mconf
$< $(silent) $(Kconfig)
之后,运行的结果如下图所示,请和前面的config FRONTSWAP 内容核对,就会大概明白其中一些含义:
首页面:
mm页面FRONTSWAP配置:
只是,因为kernel配置项繁多,要了解全部配置项基本是不可能,也不必要的。这种方式只是给你提供了一个入口,然后针对性修改相关项。通常,你可以基于某一个默认配置项文件进行配置,然后再通过这个menuconfig修改特定项。不同的架构有不同的默认文件,比如x86平台,可以在arch/x86/configs
找到相关文件:i386_defconfig。通过执行make i386_defconfig