linux内核vmlinux生成过程简要分析

最近工作不太忙,研究了一下Linux内核的编译过程,在此简要记录一下。

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

linux的内核 zImage 的生成依赖于 vmlinux。

分析内核的底层 makefile 如下:

vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE
	+$(call if_changed,link-vmlinux)
	
vmlinux_prereq: $(vmlinux-deps) FORCE

发现vmlinux的生成主要依赖于 vmlinux-deps。

export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)
export KBUILD_VMLINUX_LIBS := $(libs-y1)
export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds

vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS)

KBUILD_LDS:是一个链接文件
KBUILD_VMLINUX_MAIN:是一些库和驱动

这里重点分析一下KBUILD_VMLINUX_INIT

init-y		:= $(patsubst %/, %/built-in.o, $(init-y))
...
KBUILD_VMLINUX_INIT := $(head-y) $(init-y)

可以看出来 KBUILD_VMLINUX_INIT 是各个字目录下的 built-in.o 文件。

那么 built-in.o 是怎么来的呢?
查看 /scripts/Makefile.build 文件

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
...
$(builtin-target): $(obj-y) FORCE
	$(call if_changed,link_o_target)

各个目录下的 built-in.o 依赖 (obj-y),至此已经明朗了,$(obj-y) 就是各个目录下的源文件编译出来的 *.o 文件。

拓展:
当我们在内核中添加自己的源码 并希望其编译进内核时,通常在子目录下这样修改makefile

...
obj-y += myself_file.o
...

在makefile文件中,$(obj-y) 的顺序也很重要,是源码的编译顺序 以及链接到built-in.o 中的顺序。所以一些初始化函数 (module_init() / _initcall)会在启动的时候按照排列顺序调用,一旦改变链接顺序,也可能会改变设备的初始化顺序,因此会导致系统启动出现问题。

猜你喜欢

转载自blog.csdn.net/weixin_44698673/article/details/128845871