#based on v2.6.26 kernel
Linux內核Makefile編譯生成內核目標文件的過程
直接執行make的編譯過程
- 1.先找到入口點(入口點問題)
#編譯內核line502,直接執行make默認編譯此項 all: vmlinux #編譯模塊line1037,選擇編譯模塊的話會到這里,另外還有其他許多all:target存在,為什么默認執行all: vmlinux ? all: modules
- 2.繼續找vmlinux目標
# vmlinux image - including updated kernel symbols # vmlinux目標在line806 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE # FORCE是偽目標,make假定偽目標的時間戳總是最新的,即總是被修改過,因此以它為“依賴”的“目標”“vmlinux”在每次make的時候都會被編譯。
- 3.理解$(vmlinux-lds) $(vmlinux-init) $(vmlinux-main)這個變量的作用
# line656 vmlinux-init := $(head-y) $(init-y) # -y是指配置為yes表示加入內核,-m是指配置為module,-n是指配置為no表示不加入內核 vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) vmlinux-all := $(vmlinux-init) $(vmlinux-main) vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds # SRCARCH為體系結構名,這里我們使用x86
生成的vmlinux.lds目標文件是鏈接生成vmlinux映像的鏈接描述文件ld script,從該文件中我們大致可以知道vmlinux映像的頭部是$(head-y) $(init-y),vmlinux映像的主體部分是$(core-y) $(libs-y) $(drivers-y) $(net-y)等.具體我們可以仔細研究ld script to make i386 Linux kernel.
vmlinux映像 #################################################### # # # # $(head-y) # $(core-y) $(libs-y) # # $(init-y) # $(drivers-y) $(net-y),etc. # # # # ####################################################
- 找出$(vmlinux-init)或者說$(head-y) $(init-y)包含那些文件
先找init-y,輕易搞定如下:
# line452 init-y := init/ # line621 init-y := $(patsubst %/, %/built-in.o, $(init-y)) ## 表示將$(init-y)列表中"/"替換為"/built-in.o",也就是最終init-y == init/built-in.o
init/built-in.o目標在init目錄下生成,其中包含start_kernel函數,這個函數是從啟動代碼進入linux kernel的點.
在根目錄下的Makefile文件中我們找不到head-y的定義,那么head-y肯定在某個被包含(include)進來的文件中. 通過搜索include我們發現head-y可能在/arch/x86/Makefile中.
# line431 include $(srctree)/arch/$(SRCARCH)/Makefile
果然,在/arch/x86/Makefile中找到head-y,
# line161 head-y := arch/x86/kernel/head_$(BITS).o ## BITS是CPU處理的位數的定義,我們使用的32位CPU,這里直接使用32來代替,文件也就是head_32.o head-y += arch/x86/kernel/head$(BITS).o # head32.o head-y += arch/x86/kernel/init_task.o
- vmlinux映像生成的一般規則綜述
通過以上分析路徑
all --> vmlinux --> $(vmlinux-lds) $(vmlinux-init) --> $(head-y) $(init-y) -- --> built-in.o head32.o head_32.o init_task.o --> *.c *.S
我們可以有了一個大致的概念,那就是通過內核配置信息,我們有了xxxx-y的目標列表,通過深度遍歷依次去生成這些目標,並最終生成了vmlinux.
至於內核配置信息與xxxx-y的目標列表以及依然的目錄文件等,是如何映射匹配的,還需要更仔細的分析.
- bzimage - 對vmlinux映像的后續處理
並且在/arch/x86/Makefile中我們還可以發現對vmlinux映像的后續處理部分,后續處理之后的bzimage將會是
bzimage #################################################### # # # # # Setup # uncompress code # compressed vmlinux # # # # # ####################################################
接下來我們看看對vmlinux映像的后續處理部分的Makefile,首先要找到起點:
# line200 of /arch/x86/Makefile #### # boot loader support. Several targets are kept for legacy purposes boot := arch/x86/boot PHONY += zImage bzImage compressed zlilo bzlilo \ zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install # Default kernel to build all: bzImage # KBUILD_IMAGE specify target image being built KBUILD_IMAGE := $(boot)/bzImage zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage zImage bzImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE) ## 進入arch/x86/boot目錄執行其Makefile $(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/bzImage compressed: zImage