資源描述:
《linux內(nèi)核入門(mén) Chapter 9》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、第9章編譯Linux內(nèi)核本章包括:9.1工具鏈9.2編譯內(nèi)核源代碼小結(jié)習(xí)題到此為止,我們已經(jīng)認(rèn)識(shí)了linux內(nèi)核子系統(tǒng),也探究了系統(tǒng)的初始化函數(shù)。同樣,了解內(nèi)核映像的創(chuàng)建也是非常重要的。本章將討論內(nèi)核映像的編譯和鏈接過(guò)程,并考察內(nèi)核的編譯過(guò)程。9.1工具鏈(toolchain)工具鏈(toolchain)是創(chuàng)建linux內(nèi)核映像的一組程序集合。鏈的概念源于一工具的輸出將作為另一工具的輸入這一特點(diǎn)。工具鏈包含編譯程序、匯編程序和鏈接程序。從技術(shù)上講,還需一個(gè)文本編輯器。本節(jié)只討論前三個(gè)工具。開(kāi)發(fā)軟件時(shí)工具鏈必不可少,當(dāng)然,軟件
2、開(kāi)發(fā)工具包(SDK)也是必需的。編譯程序(compiler)是一個(gè)轉(zhuǎn)換程序,可將高級(jí)源語(yǔ)言轉(zhuǎn)換成低級(jí)目標(biāo)語(yǔ)言(objectlanguage)。目標(biāo)代碼是運(yùn)行在目標(biāo)系統(tǒng)上并依賴于機(jī)器的一系列指令。匯編程序(assembler)也是一個(gè)轉(zhuǎn)換程序,可將匯編語(yǔ)言轉(zhuǎn)換成與編譯程序相同的目標(biāo)代碼。其不同之處在于:匯編程序產(chǎn)生的機(jī)器指令與匯編語(yǔ)句一一對(duì)應(yīng),而高級(jí)語(yǔ)言的每條語(yǔ)句可能對(duì)應(yīng)多條機(jī)器指令。如你所知,linux源代碼中與體系結(jié)構(gòu)相關(guān)的某些文件是用匯編語(yǔ)言編寫(xiě)的,它們調(diào)用匯編程序?qū)⑵渚幾g為目標(biāo)代碼。鏈接編輯程序(linkeditor)
3、或鏈接程序(linker)可將多個(gè)可執(zhí)行模塊鏈接成一個(gè)單元,以便執(zhí)行。圖9.1說(shuō)明了工具鏈的鏈?zhǔn)疥P(guān)系。鏈接程序?qū)殉绦虻哪繕?biāo)代碼與它使用的所有函數(shù)庫(kù)鏈接起來(lái)。編譯程序中含有標(biāo)志位,可供用戶選擇編譯級(jí)別。例如:圖9.1中可以看到,編譯程序可以直接產(chǎn)生機(jī)器代碼,也可以先編譯成匯編語(yǔ)言,再經(jīng)由匯編程序把它組合成計(jì)算機(jī)可直接執(zhí)行的機(jī)器指令。9.1.1編譯程序通常,編譯程序也具有鏈?zhǔn)教匦?,它分成多步?zhí)行,一步的輸出作為下一步的輸入,圖9.2是其圖解。編譯的第一步是詞法掃描(scanner),它將高級(jí)語(yǔ)言編寫(xiě)的程序拆分為一一個(gè)個(gè)的單詞符
4、號(hào)(tokens)。接下來(lái),語(yǔ)法分析(parser)階段根據(jù)一定的語(yǔ)法規(guī)則將這些符號(hào)組織起來(lái),并由上下文分析階段根據(jù)語(yǔ)義屬性進(jìn)一步組織這些符號(hào)。優(yōu)化程序可提高所解析的符號(hào)的效率,代碼生成階段則產(chǎn)生目標(biāo)代碼。編譯程序輸出符號(hào)表和可重定位的目標(biāo)代碼。換句話說(shuō),每一個(gè)已編譯的模塊其起始地址都是0,鏈接時(shí)必須重定位到合適的位置。圖9.2編譯程序的操作過(guò)程9.1.2交叉編譯工具包通常自然地(natively)運(yùn)行,這就意味著編譯代碼的系統(tǒng)和運(yùn)行目標(biāo)代碼的系統(tǒng)相同。如果在x86系統(tǒng)上開(kāi)發(fā)了一個(gè)內(nèi)核,把它裝載到另一個(gè)(或同樣的)x86系統(tǒng)
5、上時(shí),無(wú)須進(jìn)行任何編譯工作。功能強(qiáng)大的Macs和數(shù)量繁多的x86工具包可將代碼編譯成能在相應(yīng)體系結(jié)構(gòu)上運(yùn)行的代碼。但是,如果我們想在一種平臺(tái)下編寫(xiě)代碼,而在另一種平臺(tái)下運(yùn)行呢?聽(tīng)來(lái)容易做來(lái)難!考慮一下嵌入式市場(chǎng),嵌入式系統(tǒng)通常是在有限內(nèi)存和I/O接口的環(huán)境中實(shí)現(xiàn)其功能。無(wú)論控制的是汽車(chē),路由器還是手機(jī),這些設(shè)備都不足以容納一個(gè)完整的嵌入式系統(tǒng)開(kāi)發(fā)環(huán)境(更不用說(shuō)監(jiān)視器和鍵盤(pán))。解決的辦法就是,讓開(kāi)發(fā)者利用他們功能強(qiáng)大、相對(duì)廉價(jià)的工作站作為宿主機(jī)(hostsystems)來(lái)開(kāi)發(fā)代碼,然后將這些代碼下載到目標(biāo)系統(tǒng)(targetsy
6、stem)上進(jìn)行檢測(cè)。因而稱之為交叉編譯!例如:你可能是PowerPC嵌入式系統(tǒng)的開(kāi)發(fā)者,該系統(tǒng)使用405處理器。而你的臺(tái)式機(jī)絕大多數(shù)都是x86的。通過(guò)使用gcc,你可以在這些臺(tái)式機(jī)上完成所有開(kāi)發(fā)工作(包括C程序和匯編程序),只要在編譯時(shí)使用-mcpu=405選項(xiàng)了解更多應(yīng)用于IBMRS/6000(POWER)及PowerPC的gcc選項(xiàng),可登錄:http://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#RS_002f6000-and-Pow
7、erPC-Options就可以了。這樣產(chǎn)生的目標(biāo)代碼具有405處理器特有的指令和尋址方式。之后就可以把目標(biāo)代碼下載到嵌入式系統(tǒng)中運(yùn)行并調(diào)試。這樣做看起來(lái)確實(shí)很乏味,但是對(duì)資源有限的嵌入式系統(tǒng)而言,它大大節(jié)省了內(nèi)存。在這種特殊環(huán)境下,許多用于交叉編譯的輔助開(kāi)發(fā)調(diào)試工具也應(yīng)運(yùn)而生。9.1.3鏈接程序編譯一個(gè)C程序時(shí)(例如,“Helloworld”),生成的代碼遠(yuǎn)不止.c文件中的這三四行。鏈接程序的工作就是找出所有引用的外部模塊并鏈接起來(lái)。這些外部模塊或函數(shù)庫(kù)一般來(lái)自于開(kāi)發(fā)者、操作系統(tǒng)和C運(yùn)行庫(kù)(printf()的出處)。鏈接程序
8、取出這些函數(shù)庫(kù),修訂指針位置(重定位),并交叉引用模塊中的解析符號(hào),最終產(chǎn)生一個(gè)可執(zhí)行模塊。符號(hào)可以是全局的也可以是局部的。全局符號(hào)可以在模塊內(nèi)部定義,或由另一模塊外部引用。鏈接程序要找到與模塊相關(guān)的所有符號(hào)的定義。(注意:內(nèi)核開(kāi)發(fā)者無(wú)法使用用戶函數(shù)庫(kù)。)對(duì)于普通函數(shù),內(nèi)核自身有對(duì)應(yīng)的函數(shù)