以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
錯漏之處還望不吝指出