真假vmlinux–由vmlinux.bin揭开的秘密

真没有想到,在编译过内核的源码目录下,你可以找到两个同叫vmlinux的文件。

$find . -name vmlinux
./vmlinux
./arch/x86/boot/compressed/vmlinux

怎么样,你之前有发现过么?这还是在探索vmlinux.bin的过程中发现的秘密。

他们究竟都是干什么用的?有什么联系?和bzImage之间有关联么?让我们来揭开这神秘的面纱。

隐藏的vmlinux

老规矩,先来看看vmlinux.bin的规则。

$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
	$(call if_changed,objcopy)

嗯,看到刚才find中发现的vmlinux了不?原来vmlinux.bin是这个vmlinux通过objcopy而来。那这个都包含了谁? 又和根目录下的vmlinux有什么关系呢?你们俩真是太像了。

$(obj)/compressed/vmlinux: FORCE
	$(Q)$(MAKE) $(build)=$(obj)/compressed $@

原来老人家还有一个单独的目录,再次调用了make命令。

揭开面纱

检验基本功的时候又来了,还记得这个命令究竟是做了什么么?还记得这个时候,规则文件是要去哪里找么?如果想不起来可以去回顾前面几篇入门文章。

在arch/x86/boot/compressd/Makefile中,找到了规则:

偷个懒,猜一下,这个vmlinux就是把变量vmlinux-objs-y中的所有目标链接而成的。是不是觉得易如反掌了?

好,那来看看这个变量里都有谁。

好少啊,感觉比setup.bin还少。貌似挺简单的啊,这么着就算是把整个bzImage的编译流程都走完了~

真的完了么? 你有没有发现什么不对劲?

对了,我们的根目录的vmlinux呢?难道放到启动目录下的内核里面没有根目录的vmlinux?不对啊,根目录的vmlinux可是包含了所有内核真正的代码的啊。

是的,你发现的没错,我们还没有真正走到内核编译的最深处。

石破惊天

也不知道是什么机缘巧合,竟然发现在arch/x86/boot/compress/目录下面的piggy.S这个文件是编译时生成的。

在我的环境上,这个文件看上去像是这样:

怎么样,你有没有觉得大跌眼镜?简直就是FXXK。

在汇编代码中直接包含了一个文件。让我们看看这个incbin语句是什么含义吧。

哥们直接把整个内核给包进来了,小生佩服。

再烧一次脑

为了确认,我们再来看看这个vmlinux.bin.gz是不是真的是内核的代码。

注意,下面的关系还真是有点烧脑。

先来看vmlinux.bin.gz:

那再来看$(obj)/vmlinux.bin。注意哦,这个已经是arch/x86/boot/compressed/vmlinux.bin,而不是arxh/x86/boot/vmlinux.bin了。怎么样,是不是有点烧脑?

而这个时候的依赖,vmlinux,就是根目录下的vmlinux了。

At last。

终于,我们看清楚了内核代码是怎么样打包到bzImage中了。

一张图解说

我知道,你肯定已经晕的不能再晕了。我们还是用一张图来解说一下。

是不是稍微的清晰了那么一些些?

真相大白

终于知道了内核还会被压缩,还会被放在一个叫piggy.o的文件中,然后再被打包成一个bzImage放到启动目录中被加载。

没想到内核的大侠们也挺逗的,起个名字尽然还有点冷幽默。

整个内核的编译过程已经基本走完了,你可能会问知道这个编译的过程除了好玩还能有什么用呢?

我想除了能用来参加面试之外,可能还有一个原因,那就是你有机会明白内核启动时的页表是长什么样的。嗯?你不知道?不着急,你的内核之旅可能才刚刚开始。

Last updated

Was this helpful?