linux配置、編譯內核實用工具

配置與編譯內核用到的工具很多,在這裏只對幾個關鍵工具進行介紹,更多的內容請參考相關手冊。

                                          Make
    Make
是一種幫助大型軟件工程的編譯工作實現自動化的編程語言。正確地使用Make可以大大減少因編譯程序而花費的時間,因爲它可以消除不必要的再編譯。Make的基本設計思想是如果目標文件是在最近一次對源文件的修改之後編譯的,它就是新的,不需要重新編譯;如果最近一次對源文件的修改之後沒有及時更新目標文件,那麼該目標文件就是舊的,需要重新編譯。爲了理解Make如何執行一個任務,需要了解一些術語:
◆目標 需要執行的一個任務。多數情況下它就是用戶要生成的文件的名字,但是它也可以僅是個任務的名字。

◆依賴關係 兩個目標之間相互依存的關係。如果修改目標B會造成目標A的修改,那麼就說目標A依賴於目標BBA的先決條件。

◆變量 一種存儲臨時信息的載體。Make中使用的變量應該加上括號,例如$TEMP)。

◆命令 執行任務時使用的指令,可以是一條、多條,甚至沒有。

◆規則 一條完整的規則具有以下格式:

目標(target) : 先決條件
(prerequisites)
規則
(command)
......
   
其中只有目標必須要有,其它成分可以沒有。一條完整的規則描述了編譯一個目標的方法和依賴關係,是Makefile中最重要的部分。

Makefile文件 描述如何生成一個或多個目標的文件。它列出目標依賴的各個文件,並提供正確編譯這些目標所需要的規則。
   
接下來以2.4.23kbuild爲例,簡要介紹一下內核的構建過程。首先,完整的內核構建過程由以下五種Makefile封裝。

   1
.根目錄
Makefile
   
它是最重要的Makefile,定義所有與體系結構無關的變量和目標。它讀取.config文件,並根據其信息最終生成vmlinuxmodulesMake通過向下遞歸調用子目錄中的Makefile來編譯這兩個目標。

    2
.配置文件
.config
   
執行“make ”會在根目錄下生成該配置文件,其內容記錄了具體的配置選擇,也可以將舊內核的配置文件放在這裏。

    3
arch/*/Makefile
   
這是與特定體系結構相關的Makefile。它包含在根目錄下的Makefile中,爲kbuild提供體系結構的特定信息。

    4
.子目錄
Makefiles
   
它們存在於每個子目錄下,大約有幾百個。它們接受來自上層Make傳遞下來的信息,並根據這些信息來構造一個需要編譯的文件列表,並交由Rules.make處理。

    5
Rules.make
   
幾乎每個子目錄Makefile都包含該Makefile。根據子目錄Makefiles構建的文件列表,Make使用Rules.make定義的通用規則來編譯所有來自列表的源文件。

     kbuild
的執行過程是:Make從根目錄Makefile開始執行,從中獲得與體系結構無關的變量和依賴關係,並同時從arch/*/Makefile中獲得體系特定的變量等信息,這些信息擴展了根目錄Makefile提供的變量。此時kbuild已經擁有構建內核需要的所有變量和目標。然後,Make進入子目錄,把部分變量傳遞給子目錄Makefile。子目錄Makefile根據配置信息決定編譯哪些源文件,從而構建出一個需要編譯的文件列表。最後,Rules.make根據其定義的編譯規則決定這些文件的編譯方式。

   
需要注意的是,由於Make的向下遞歸特性和無序性,其執行過程並不完全遵守順序逐行執行的規則,但無論Make的執行有多複雜,也只分爲兩個階段。第一個階段Make會讀取所有變量和分析所有目標的依賴關係,並最終建立一棵依賴關係樹。同時,所有的立即型變量(通過“:賦值)在這個過程中被擴展,就像C變量一樣。而在這個階段的最後,所有的延遲型變量才被擴展(通過賦值)。這點需要格外注意。第二個階段Make會根據依賴關係樹執行命令。

   
因此,一個目標和其先決條件的規則定義的順序是無所謂的,很可能一個目標的先決條件的規則定義在百行以後纔出現。Make會耐心讀完所有的Makefile後分析得出依賴關係樹。


                                 GCC
     GCC
GNU的免費編譯程序,也是內核惟一指定使用的編譯器。GCC在執行一個完整的編譯任務時會經過以下步驟:

◆預處理 GCC會調用cpp程序來分析各種宏指令,如#define#if#include等。

◆編譯 這一階段根據輸入文件產生彙編語言指令。由於通常情況下是立即調用匯編程序as,所以輸出一般不保存在文件中,可以使用-S選項強制輸出源程序的彙編版本。

◆彙編 這一階段將彙編語言源程序作爲輸入,生成.o目標文件。

◆鏈接 這是最後一個階段。該階段中,各個.o模塊被鏈接在一起構成可執行文件。

as
用戶可以明確地要求使用as來直接處理彙編文件。as產生的目標文件可以分爲文本段(.text)、數據段(.data)和未初始化數據段(.bss)。

ld
as相似,用戶可以明確地要求使用ld鏈接程序將幾個模塊組合成一個單獨的可執行文件。其鏈接過程通常由一個叫ld鏈接腳本的文件來描述。該腳本使用Linker Command Language編寫。使用“ld --verose”命令可以看到這個默認使用的ld鏈接腳本。

ar
ar
GNU的二進制文件處理程序,用於創建、修改及從歸檔文件中抽取文件。由它生成的.a歸檔文件實際上是一個包含許多可執行二進制代碼子程序集合的庫文件。


                              RPMBuild
   
使用“make rpm”可以把內核源代碼製作成RPM包。在此之前,kbuild會執行“make spec”生成rpmbuild程序用到的spec文件,詳見“man rpmbuild”


 

 

 

 

中間件
根目錄scripts下的各種腳本和C源文件都可以稱作中間件。它們並不是內核組件的一部分,只是在kbuild執行過程中的輔助程序。以split-include爲例,講述配置文件的運作機理。
.config
由關鍵字/值對組成,其內容類似於:

CONFIG_MPENTIUMIII=y

 

 

 

 

# CONFIG_MPENTIUM4 is not set

 

 

 

 

CONFIG_REISERFS_FS=m

 

 

 

 

這些信息在執行“make ”時自動生成。同時include/linux/autoconf.h依照.config的內容生成。它的格式類似於:
#define CONFIG_MPENTIUMIII 1

 

 

 

 

#undef CONFIG_MPENTIUM4

 

 

 

 

#undef  CONFIG_REISERFS_FS

 

 

 

 

#define CONFIG_REISERFS_FS_MODULE 1

 

 

 

 

對比一下不難發現,include/linux/autoconf.h明確地洞悉了.config的意圖:哪些組件不編譯,哪些需要編譯進內核,而哪些又要作爲模塊來編譯?split-include根據include/linux/autoconf.hinclude/config/下建立相關的目錄和.h文件。每個.h文件只包括include/linux/autoconf.h中的某一行,比如在配置內核選項時支持NTFS文件系統,並把它編譯進內核,在.config中就會生成“CONFIG_NTFS_FS=y”,相應地在include/linux/autoconf.h中會生成“#define CONFIG_NTFS_FS 1”一項。這樣,所有與NTFS文件系統相關的C源文件都會包含include/config/ntfs/fs.h頭文件。
   
如果以前編譯過內核,並且沒有使用過“make mrproper”.configinclude/linux/autoconf.hinclude/linux/config/就不會被刪除。這裏涉及到新舊內核的配置問題。一個全新的內核代碼是未經配置的。如果只在原內核的功能基礎上增加對NTFS的支持,那麼從頭開始配置無疑是浪費時間。可以繼續使用原內核的.config文件,而所有的配置信息不會有任何更改,並且可以直接在原配置的基礎上增加新功能。

   
在複雜的情況下,保留的舊內核配置信息還要與新的配置信息進行比較:哪些舊信息需要覆蓋,哪些需要保留?下面來看一下幾種可能的情況

  
   
舊值保存在include/config/下的.h文件中,新值保存在新生成的include/linux/autoconf.h文件中。split-include的代碼不僅描述瞭如何處理這五種情況,還描述了include/config/下文件和子目錄的生成過程。

 

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