内核编译中的小目标

王首富定过一个亿的小目标,虽然我们内核中没有一个亿,却还是有不少有意思的小目标的。

这些小目标可以帮助我们

  • 生成辅助资料

  • 生成单个目标文件

  • 节约时间

  • 偶尔可以帮助一下调试

那我们就一个个讲吧~

all 或者 空

当你在内核代码目录下执行make的时候,编译的目标默认就是这个all。

代码中的注释很好的解释了这个目标的意义。

# The all: target is the default when no target is given on the
# command line.
# This allow a user to issue only 'make' to build a kernel including modules

这个目标在x86平台 =

vmlinux + modules + bzImage

vmlinux

嗯,这个就是你编译完成后在linux源代码目录下的那个vmlinux了。

注意了,这个是一个ELF的文件哦。用处嘛,以后你会慢慢知道的。

modules

modules就是编译内核模块的。

所以整个内核,你可以理解为就是 vmlinux + modules组成的。

bzImage

那既然vmlinux + modules组成了整个内核,多出来了一个bzImage来插什么腿?

这个东西可以看作是vmlinux的衍生。你看vmlinux是ELF格式的,首先在引导程序要加载的时候你得有人看得懂这个格式,另外这个文件比较大。现在4.9的内核编译下来vmlinux就有422M这么大,直接放到启动分区实在太占地方。当然我这个没有裁剪,裁剪后应该可以相应减少,但是恐怕也不会小太多。

所以bzImage可以粗暴地理解为

ELF加载器 + 压缩了的vmlinux。

整个压缩完之后bzImage大小只有7M不到了,这压缩能力杠杠的。

M=drivers/xxx

这个可以看作是modules目标中的更小的一个目标了。

举一个栗子大家看了或许更明白。

make M=drivers/net/ethernet/intel/ixgbe/

这条命令只会去编译ixgbe这个驱动,而不需要去运行对其他驱动代码的检测。对开发或者后期维护,都节省了相应的编译时间。

dir/file.o

这是单独编译某个文件的,当你修改某个文件做开发的时候,你可以先单独编译你修改的文件确保没有语法错误,然后再编译内核或者是模块。

比如在ixgbe模块中,更改了ixgbe_ethtool.o文件,那么你可以先运行

make drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.o

来确保单个文件的语法没有错误,然后再去编译整个模块。

同样这也是可以节省编译时间的,尤其是当遇到某个文件编译有错误的时候。

dir/file.i

这个目标是针对某个文件只做到预处理,也就是把所有的头文件和宏定义都展开了。

用法很简单

make mm/memblock.i

就生成了mm/memblock.i文件,其结果是已经预处理完的,也就是个种宏定义展开后的。

感觉用处不是很多,能想到的就是在阅读内核源代码的时候可以确定到底这个宏定义的是啥。因为内核需要在不同的架构体系下运行,而且同一架构体系下又有不同的配置。所以同样一个函数或者宏会在不同情况下定义成不同的样子,有时候直接肉眼去看代码不一定能看得准。

那怎么办呢?

这个时候就可以执行这个命令,直接看预处理后的文件,或许可以有助于你理解代码那么一点点。

dir/file.s

这个作用是生成了指定文件的汇编代码。

用法类似

make mm/memblock.s

这估计是要做汇编级的调试了,俺还从来没有整过。

cscope

这个目标特殊,已经不是代码了,是生成cscope的文件。嗯,这个文件是用来辅助阅读代码的。

懂得人秒懂,不懂的估计得重新开一个话题了。

isoimage

这个还是Andi Kleen告诉我的。这是一个包含内核的可以启动的iso文件。 用来调试用的,用得真的不多。

有兴趣的朋友或许可以在我其他的文章中见到它的身影。

help

最后的最后,kbuild中提供了一个help的目标。当你不确定如何使用或者想知道还有哪些目标可以用那就执行

make help

你就可以知道都还有哪些用法了。

好了,小目标们讲完了。现在是不是对内核编译又有了点了解?强烈建议没有编译过这些小目标的筒子手动运行一下,看一看执行的结果加深内核编译过程的印象。

还是那句话

纸上得来终觉浅,绝知此事须躬行

Last updated