bzImage是怎麼來的

 

以x86架構32位機爲例,即i386

 

從經典的helloworld程序開始

理解程序的編輯、編譯、連接、運行的四個階段

內核也是使用gcc、ld等工具編譯連接出來的,並沒有什麼神祕之處

只不過文件繁多,代碼樹龐大而已,超出了大多數人的理解範圍

就好像一般人對支配幾千或幾萬塊錢還是沒有問題的

但是若突然讓其支配上億元時,一般人都是沒有概念的

 

使用的工具make、gcc、ld、objdump、readelf、nm、objcopy、gzip等

一些程序的具體參數可以使用man查看具體含義

 

簡單的瀏覽一下Documentation/kbuild目錄中的幾個文件

這幾個文件介紹了內核的構建系統、Makefile的組織層次和一些特殊的命令等

閱讀make的手冊,瞭解基本的目標規則

 

編譯之前先敲下make help,瞭解內核提供的一些參數

通過V=1參數顯示具體的編譯命令

 

內核在編譯之前利用Kbuild系統提供的config機制解析各目錄的Kconfig文件以便對內核進行剪裁

以make menuconfig爲例

由頂層的Makefile開始匹配目標文件%config

解決完一些依賴後會進入scripts/kconfig目錄執行子make

匹配scripts/kconfig/Makefile中的menuconfig目標

其依賴爲scripts/kconfig/mconf小程序

編譯出小程序mconf後,便運行該程序解析各個Kconfig文件

提供一個配置接口

配置完成後mconf便會在頂層目錄生成一個.config文件

在編譯內核的時候使用該.config文件生成

auto.conf供Makefile決定編譯哪些目錄

autoconf.h供代碼預處理

這也是config機制的2個主要作用

 

使用make的- n、-p選項查看編譯命令、變量等

以make bzImage爲例

使用內核Makefile提供的參數V=1屏蔽@以便查看編譯使用的參數和命令等

 

頂層的Makefile定義一些常用的變量、目錄信息等

會包含對應架構下的目錄下的Makefile,如arch/x86/Makefile

這樣便找到目標bzImage,其依賴爲頂層Makefile裏的目標vmlinux

 

看下vmlinux的依賴$(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE

1. vmlinux.lds爲對應架構的連接腳本,由arch/x86/kernel/vmlinux.lds.S生成

2. $(vmlinux-init)和$(vmlinux-main) 即各個.o與built-in.o文件

3. 這些vmlinux所依賴的.o目標文件由這2條規則

$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;

$(vmlinux-dirs): prepare scripts

$(Q)$(MAKE) $(build)=$@

通過命令make -f scripts/Makefile.build obj=XXX/XXX編譯所有的目錄和子目錄

總目錄的控制由頂層Makefile定義

各個子目錄的控制由其所在總目錄下的Makfile和scripts/Makefile.lib控制

$(subdir-ym):

$(Q)$(MAKE) $(build)=$@

編譯具體代碼時都是使用scripts/Makefile.build這個Makefile

各個目錄的built-in.o由對應目錄下的.o文件連接而成

4. 頂層Makefile的目標vmlinux由rule_vmlinux__ => cmd_vmlinux__中的命令連接而成

 

5 . 解決完依賴vmlinux後

便執行arch/x86/Makefile中的目標bzImage的命令

make -f scripts/Makefile.build obj=arch/x86/boot arch/x86/boot/bzImage


6. 匹配arch/x86/boot/Makefile中的

規則$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE

依賴2個2進制文件setup.bin和vmlinux.bin

 

7. 使用連接腳本arch/x86/boot/setup.ld生成setup.elf

setup.elf中的.o目標也在arch/x86/boot/Makefile中定義

使用objcopy得到依賴setup.bin

 

8. 含有壓縮映像的arch/x86/boot/compressed/vmlinux

由頂層Makefile得到的vmlinux經objcopy得到arch/x86/boot/compressed/vmlinux.bin

使用gzip壓縮vmlinux.bin得到vmlinux.bin.gz

使用arch/x86/boot/compressed/mkpiggy小程序得到arch/x86/boot/compressed/piggy.S

由arch/x86/boot/compressed/piggy.S經gcc編譯後得到piggy.o

使用連接腳本arch/x86/boot/compressed/vmlinux.lds連接head_32.o、解壓代碼、…、piggy.o等

得到arch/x86/boot/compressed/vmlinux

 

9. 目標vmlinux.bin則會依賴arch/x86/boot/compressed/vmlinux

即需要先得到含有壓縮過的vmlinux映像的連接合成文件

然後使用objcopy得到arch/x86/boot/vmlinux.bin

 

10. 最後使用小程序arch/x86/boot/tools/build將setup.bin和vmlinux.bin合併爲bzImage

 

詳細的註釋請參考git://github.com/kernel-digger/linux-2.6.git

錯漏之處還望不吝指出

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章