FreeBSD下的可執行程式格式(轉)

BSDLite發表於2007-08-15
FreeBSD下的可執行程式格式(轉)[@more@]在 FreeBSD下的可執行程式通常可分為兩類,一類為使用各種解釋語言編寫的指令碼,如sh、awk、perl、Tcl等,這些程式需要解釋程式進行解釋執行,小巧方便,對於實現不常使用、不要求效率的程式非常有用;另一類就是使用C等高階語言編譯後產生的可執行二進位制程式。

1) 解釋指令碼程式

使用 file命令可以確認檔案的型別,包括可以確定一個程式是可直接執行的二進位制程式,還是解釋指令碼程式。


$ file a.out

a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically

linked (uses shared libs), not stripped

$ file /etc/rc

/etc/rc: Bourne shell script text executable


Unix之所以功能強大,原因之一就在於它提供了強大的再開發能力。這不僅與提供了高階語言C的編譯器有關,而且也與提供了很多種能以解釋方式執行的簡單指令碼語言有關。解釋程式指令碼的特點是方便性、簡單靈活,而且也比較容易學習入手。很多情況下,需要完成的工作任務功能比較單一,並不需要頻繁執行,而且要求快速編寫出來,這就適合使用解釋型語言編寫,並且解釋程式本身就具備處理文字和字串的便捷性,並能夠和很多現有程式透過系統提供的管道、環境變數等方式結合起來,使得它們非常適合實現文字處理功能。

解釋語言的缺點是每次執行程式時都要載入語言的直譯器,解釋執行程式,因而效率較低,並且不能直接操縱記憶體和 I/O裝置,不適合編寫大型程式和對效率要求較高的場合。

每個解釋指令碼程式的第一行指出該指令碼程式使用的直譯器,例如一個普通的 shell程式的第一行為:


#! /bin/sh

不同的解釋語言可用在不同的方面,最常用的有 shell解釋程式,依據使用shell的不同,也分為不同的shell指令碼,基本上也分為sh和csh兩種不同的風格。系統管理中經常使用shell程式來執行一些日常管理任務,很多軟體也使用shell程式來提供輔助安裝和設定任務。perl也是一種常用的、功能強大的解釋語言,它兼有解釋性程式的方便性和高階程式語言的強大功能,使程式設計師能在很短的時間內寫出非常有效的程式。因此perl得到了眾多程式設計師的支援,透過為perl開發了更多的程式模組,進一步使得perl的處理能力變得更為強大。當前perl已經成為了最流行的一種解釋語言,尤其在編寫Web伺服器上的CGI程式方面,更是處於無可爭議的地位。Tcl/tk是另一種解釋語言,它能用在X Window系統下,使用描述語言顯示不同的X控制元件,因此很多X應用程式使用它來建立自己的圖形介面。

2) 二進位制執行程式

使用高階語言編寫、並經過編譯得到的二進位制執行程式執行效率更高,並且只有二進位制格式的執行檔案才能充分利用 Unix系統提供的全部功能。同樣系統核心也是一個特殊格式的二進位制執行檔案。

早期的 Unix使用a.out格式作為它的執行檔案格式,隨著Unix的發展,又出現了其他幾種執行檔案的格式,當前最重要的執行檔案格式為ELF格式,採用這種格式的最初想法是為了在不同平臺間採用相同的執行檔案格式,並實現動態共享連線庫。雖然ELF檔案格式並沒有達到AT&T最初設想的全部目的,但這種檔案格式卻成為最流行的執行檔案格式。除此之外,實際使用的檔案格式還有一種較老的COFF格式,這種格式是在Unix System V R3.2中使用的,當前只有老版本的SCO Unix中還在使用它,而SCO也正逐漸轉向ELF格式。

FreeBSD可以同時支援這兩種執行檔案的格式,FreeBSD 2.2.x之前的版本使用a.out格式作為預設的執行檔案格式,到FreeBSD 3.x之後ELF格式成為預設的執行檔案格式,並且以後會徹底轉向ELF。事實上在FreeBSD下的a.out格式具備了相當多的特性,如動態連線等ELF格式具備的特性,也有一些ELF格式不具備的特性,如壓縮執行檔案格式。但由於FreeBSD中使用的編譯器gcc決定不再支援a.out格式的緣故,因此FreeBSD也必須轉向ELF格式。這也是當前還支援a.out格式的FreeBSD版本預設使用較老版本編譯器的原因之一。

在 FreeBSD中,a.out格式的執行檔案可以支援壓縮執行格式,這使得使用gzip壓縮過的a.out格式的執行檔案也能立即執行。ELF格式的程式不提供這種支援。

FreeBSD的檔案格式從aout到ELF的轉變是漸變的,首先是在3.0-RELEASE中將執行程式的預設格式轉變為ELF格式,核心檔案還保持aout格式,直至FreeBSD-3.1,全部執行檔案格式才預設設定為ELF格式。

轉向 ELF也造成很多相關程式的轉變,如原有的Boot Loader不支援ELF格式的核心,3.1-RELEASE就升級到新Boot Loader;而原有的可載入模組lkm為aout格式,也需要轉向ELF格式的modules。新可載入模組的位置為/modules目錄,並使用kldload、klduload、kldstat來進行管理。(aout格式的模組管理命令為modload、modstat和modunload)。

a.out和ELF格式使用的庫檔案也是不同的,使用ELF執行檔案格式的FreeBSD 3.x中,/usr/lib下為ELF格式的函式庫,而用一個子目錄/usr/lib/aout存放a.out格式的函式庫,用於相容2.2.x之前版本的FreeBSD程式。但這給一些使用包裝技術的軟體(一些中文外掛系統)造成了一些小麻煩。對不同格式的執行檔案要使用不同的包裝庫,系統不會將與程式本身格式不同的連線庫連線到程式上,對應的錯誤資訊為 “ bad magic ” ,指出檔案格式的不同。

由於 3.x之後的預設格式為elf格式,為了生成a.out格式的檔案,必須在編譯和連線時使用 -aout引數,告訴編譯器gcc和聯結器ld使用不同的格式生成執行檔案。

3) 靜態連線和動態連線

在作業系統發展的早期,除了核心提供的介面,所有的庫函式都要連線到程式中,這樣所有的程式都可以直接在系統核心下執行。然而事實上大部分程式都會使用一些相同的庫函式,尤其是在使用高階語言程式設計的時候,通常都使用同樣的庫。例如, C語言編寫的程式通常都使用printf函式進行輸出,使用scanf讀入使用者輸入內容。如果每個庫函式都連線到使用者程式中,這樣每個程式都會包括這個函式的一個複製,就浪費了記憶體空間。

因此,現代作業系統使用動態連線的技術,不將常用的庫直接編譯進每個程式中,而是保留相應的介面,在核心載入程式時,再使用動態連線程式將庫載入並和執行程式連線起來。這就是動態連線的技術,由於庫和程式是分別載入的,因此多個程式可以共享一個庫的同一個複製,節約了資源。

不論對於 a.out格式還是ELF格式,FreeBSD均支援動態連線,因此應用程式預設就使用動態連線的方式。如果想使用靜態連線,可以在應用程式編譯連線時,指定-static連線選項,將目標程式連線成靜態連線的執行檔案。由於庫程式碼被連線進執行檔案中,靜態連線的執行檔案要比動態連線的執行檔案要大。
QUOTE:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-958890/,如需轉載,請註明出處,否則將追究法律責任。

FreeBSD下的可執行程式格式(轉)
請登入後發表評論 登入
全部評論

相關文章