Prelink
是
Red Hat
開發人員
Jakub Jelinek
所設計的工具,正如其名字所示,
Prelink
利用事先連結代替運行時連結的方法來加速共用庫的載入,它不僅可以加快起動速度,還可以減少部分記憶體開銷,是各種
Linux
架構上用於減少程式載入時間、縮短系統啟動時間和加快應用程式啟動的很受歡迎的一個工具。
我們在上一章中詳細介紹了動態連結和載入的過程,這種運行時的動態連結尤其是重定位
(relocation)
的開銷對於大型系統來說是很大的。相比之下,早期
UNIX
下的
a.out
格式的老式連結方法在速度和佔用記憶體方面有明顯的優勢(但不如
ELF
格式更靈活,能方便的構建動態共用程式庫)。
Prelink
工具是試圖在保持一部分靈活性的基礎上,借鑒
a.out
格式在速度和佔用記憶體方面的優點,對
ELF
檔案進行一些改進。
事實上,
Prelink
工具的原理主要基於這樣一個事實:動態連結和載入的過程開銷很大,並且在大多數的系統上
,
函數庫並不會常常被更動
,
每次程式被執行時所進行的連結動作都是完全相同的,對於嵌入式系統來說尤其如此。因此,這一過程可以改在運行時之前就可以預先處理好,即花一些時間利用
Prelink
工具對動態共用程式庫和可執行檔進行處理,修改這些二進位檔案並加入相應的重定位等資訊,節約了本來在程式啟動時的比較耗時的查詢函數地址等工作,這樣可以減少程式啟動的時間,同時也減少了記憶體的耗用。
Prelink
的這種做法當然也有代價:我們每次更新動態共用程式庫時,相關的可執行檔都需要重新執行一遍
Prelink
才能保證有效,因為新的共用庫中的符號資訊、地址等很可能與原來的已經不同了。這種代價對於嵌入式系統的開發人員來說可能稍微帶來一些複雜度,不過好在對使用者來說幾乎是可以忽略的。
更多有關
Prelink
的具體做法和細節讀者可以參考
Prelink
的開發人員
Jakub Jelinek
的專文介紹:
http://people.redhat.com/jakub/prelink/prelink.pdf
。
很多
Linux
的發行版上已經預裝了或者已經使用了
Prelink
工具,不過我們需要專門的針對嵌入式體系,比如
ARM
的版本,這樣我們需要到
Red Hat
的網站下載原始碼並重新編譯。是:
http://people.redhat.com/jakub/prelink/
編譯時間主要是
configure
時設定
--host
參數,注意它是一個用於主機而不是開發板上的工具,不要用
arm-linux-gcc
編譯它,如下所示:
# ./configure --prefix=/opt/tools/arm/prelink --host=arm-linux # make # make install |
Prelink
工具的使用非常簡單,對一個系統來說可能要花幾分鐘或者十幾分鐘。一般來說我們不用在命令列中直接指定
ELF
檔案的方式,而是將需要
Prelink
的檔案寫到設定檔
/etc/prelink.conf
中,然後使用下面的命令即可:
如果你要取消已經做了的
Prelink
也非常簡單,運行:
Prelink
常用的選項含義如下:
-a
對所有的檔案進行
Prelink
,包括
/etc/prelink.conf
檔案中指定目錄下的所有程式
-m
節省虛擬定址分配,在有許多程式需要串連時使用
-f
重新強制預串連已經串連的程式,主要用於更新串連資料時使用
-R
在給庫指定地址時,使用隨機地址,這有利於提高系統安全以防緩衝區溢位
-u
取消已做的預串連
下面是一份
/etc/prelink.conf
檔案的樣本:
# This config file contains a list of directories both with binaries # and libraries prelink should consider by default. # If a directory name is prefixed with `-l ', the directory hierarchy # will be walked as long as filesystem boundaries are not crossed. # If a directory name is prefixed with `-h ', symbolic links in a # directory hierarchy are followed. # Blacklist specification should be prefixed by -b # and optionally also -l or -h if needed. -l /opt/lib -l /opt/bin -l /opt/qte/lib |
其中以
”#”
開頭的行為注釋,正如注釋中所解釋的,下面列出的檔案目錄分別可以有
”-l”, “-h”
和
”-b”
開頭,
”-l”
和
“-h”
區分是否包括符號連線類型的目錄,
”-b”
指黑名單,即應該排除出去的部分。
你可能會在
Prelink
時遇到類似這樣的錯誤:
"Cannot prelink against non-PIC shared library"
。
這是因為有些庫沒有使用
-fPIC gcc
選項編譯。
PIC
指
Postion Independent Code
,即位置無關代碼,是動態連結的一項技術,也是
Prelink
的前提條件。這種問題只需要用
-fPIC
重新編譯代碼就可以了。
根據筆者的經驗,如果你的嵌入式系統
中動態庫過多過慢是系統效能的瓶頸之一,推薦你試試
Prelink
的方法。在筆者工作的平台上,它是非常行之有效,讓大多數應用的啟動時間及系統啟動時間都有了顯著的提升。