Gentoo Linux Prelink 指南
1.
簡介
什麼是 Prelink ? 它能為我做什麼 ?
許多的應用程式使用共用函式庫. 在這些程式被執行的時候,
共用函式庫會被讀進記憶體中, 並且跟程式中所參用到的符號(symbol)連結起來.
對大多的小程式而言, 通常這樣的動態連結非常快.
但是對一些依存於大量函式庫的 C++ 程式而言, 動態連結卻可能花上不少的時間.
在大多數的系統上, 函式庫並不會常常被更動, 每次程式被執行時所進行的連結動作都是完
全相同的,Prelink 利用這點, 將程式與函式庫連結的方式弄出來記錄在執行檔中,
達成"預先連結"的效果.
"預先連結"能夠節省應用程式的啟動時間.
以典型的 KDE 程式為例, 程式的讀取時間能夠減少 50% 那麼多.
唯一必要的維護只有每當被"預先連結"過的執行檔所連結到的函式庫有所更新時,
需要再次執行 prelink.
摘要
-
我們可以用一個就叫做 prelink 的程式來進行"預先連結".
它能夠修改執行檔的內容, 使啟動的時間變短.
-
如果某個"預先連結"過的應用程式所依存的函式庫有所變動,
您必須重新"預先連結"這個應用程式, 不然速度上的增快將繼續無法作用.
也就是說, 每次您用 portage 更新一些套件而更新了一些函式庫,
這些函式庫必須重新被"預先連結"起來.
-
對執行檔的更動是完全可逆的. prelink 擁有復原的功能.
-
目前的 Portage 能夠應付 prelink 對執行檔的 MD5sum 與 mtime 造成的改變.
-
你不用在 make.conf 中設定 FEATURES="prelink";如果
Portage可以找到 prelink 函式庫,他會自動支援 prelink。
2.
設定 Prelink
安裝所需程式
首先你要安裝 prelink 工具。emerge 程式能夠自動測試您的系統是否能夠安全
正常地進行"預先連結".
原始碼 2.1: 安裝 Prelink |
# emerge prelink
|
有不少人在安裝 prelink 的時候遭遇到測試失敗的錯誤訊息.
這些測試是為了安全理由才被放上的, 如果您關閉這些測試, prelink 的行為將無法保證.
這些錯誤大多是由這些核心套件造成: binutils, gcc, 及 glibc. 試試看照以上順序重新
安裝這些套件.
注意:
小提示: 如果您在嘗試自行手動編譯測試 prelink (./configure ;
make ; make check )時遭遇到錯誤, 您可以察看 testsuite 目錄中的
*.log 檔案, 它們可能能給您一些有用的線索.
|
如果您能提出一套能在多個系統上復現產生 emerge 錯誤的步驟,
請 e-mail 給 Stefan Jones.
系統的準備
接下來你要在 /etc/make.conf 檔案中啟動 "pic" USE 設定。不要忘了執
行 emerge --update --deep --newuse world 讓 USE 設定改變套用到整個系統。
並且確定在 CFLAGS/CXXFLAGS 中沒有設定 -fPIC。如果有的話,你需要重新編譯
整個系統。
組態設定
執行 env-update 後會產生 /etc/prelink.conf 檔,告訴
prelink 哪些檔案需要"預先連結".
原始碼 2.2: 執行 env-update |
# env-update
|
可惜的是您沒辦法"預先連結"舊版 binutils 編出來的程式.
大多這些來自預先編好, 執行檔發佈的套件都被安裝在 /opt.
編寫以下檔案能告知 prelink 不要嘗試去"預先連結"它們.
原始碼 2.3: /etc/env.d/60prelink |
PRELINK_PATH_MASK="/opt"
|
注意:
您可以用冒號分隔加入更多的目錄在這個清單中.
|
3.
進行"預先連結"
Prelink 使用方式
我們可以用下列指令來"預先連結"所有列在 /etc/prelink.conf 中的目錄裡
的執行檔.
原始碼 3.1: 預先連結清單中的檔案 |
# prelink -amR
|
警告:
有人發現如果您在磁碟空間吃緊的時候"預先連結"系統上所有執行檔,
您的執行檔有可能會被截斷, 這樣會弄爆您的系統.
您可以用 file 或 readelf 來檢查執行檔的狀態.
或者每次在進行"預先連結"前先用 df -h 檢查硬碟的剩餘空間.
|
| 每個選項的解說: |
| -a |
"All": 對所有執行檔進行"預先連結". |
| -m |
節省虛擬定址分配. 如果您有一卡車的函式庫要"預先連結"就會需要這個選項.
(譯註: 這裡的原文 virtual memory space 是有問題的, 應該是 virtual address
space 比較正確.)
|
| -R |
Random -- 用亂數進行定址分配, 這樣可以增進安全性對緩衝區溢出(buffer overflow)
攻擊的抵抗能力.
|
注意:
如想知道更多的選項細節, 請見 man prelink.
|
Prelink 後加速 KDE
KDE 的載入時間可以在 Prelink 後極大的減少。如果您通知 KDE 已經完成 prelink 的
步驟, kdeinit 的載入動作(因為不再需要)。這將會更加加速 KDE 的動作。
在 /etc/env.d/99kde-env 內將 KDE_IS_PRELINKED="true" 設定好
來通知 KDE 關於 prelink 的動作。
4.
已知問題與處理
"Cannot prelink against non-PIC shared library"
這個問題是由那些沒有使用 -fPIC gcc 選項編譯全部目的檔(object file)的問題函式庫所
造成.
這裡有一些函式庫是還沒修正或是無法修正的:
-
wine 套件中的函式庫, winex 也不例外.
但是"預先連結"本來就無法對 MS Windows 執行檔進行加速.
-
media-video/mjpegtools 中的函式庫
/usr/lib/liblavfile-1.6.so.0.
如果您的問題函式庫沒有在列表中, 請回報,
最好能夠附上一份為相映的 CFLAGS 加上 -fPIC 選項的修補檔.
當我對整個系統進行"預先連結"之後, 一些靜態連結的執行檔不會動了
就 glibc 而言是沒有 100% 的靜態連結執行檔這回事的.
如果您是用 glibc 靜態編譯了一個執行檔, 則這個執行檔還是有可能會依存其它系統檔案.
以下是 Dick Howell 的解釋.
"我想您的想法是認為所有相依函式庫都會在下載下來的檔案之中(譯註: 下載下來的
靜態連結執行檔), 所以它不用依賴任何本地端的函式庫. 但是很可惜的, 對於 Linux, 甚
至我想對於任何使用 glibc 的系統, 這樣的想法並不正確. 有個叫做 "libnss"
的東西 (名稱服務選擇 name service switch, 也有人管它叫網路安全系統, network
security system), 它提供了一些處理認證資料庫, 網路資訊, 以及一些其它東西的函式.
它被設計來使應用程式可以直接適應於不同的網路環境. 這是個聰明的設計, 但是使用不同
系統的 glibc 卻可能對它的載入造成問題. 但它又根據不同的系統設定而有所不同, 所以
您沒辦法對它作靜態連結. 我想問題就是這樣發生的, 程式靜態連結了不同系統的 glibc
函式庫, 主要是 "libpthread", "libm", "libc", 這些
函式庫對 "libnss" 呼叫了不相容的函式."
Prelink 發出 "prelink: dso.c:306: fdopen_dso: Assertion
`j == k' failed." 並中止了
這是個已知的問題,
這裡 有親切的解說. Prelink 沒辦法處理用 UPX 壓縮過的執行檔. 直到了
prelink-20021213 都還沒有修正, 您只能在進行"預先連結"時把這些壓縮過的執行檔藏起來.
您可以參考上方的 組態設定 章節 來簡單地完成這件事.
我使用 grsecurity 而"預先連結"似乎無法運作
如果您要在一個使用 grsecurity 使 mmap() 基底位址亂數化(randomized mmap() base)的
系統上使用"預先連結", 您必須把 /lib/ld-2.3.*.so 的 "randomized
mmap() base" 設定關閉. 您可以用 chpax 公用程式來完成這個動作,但是這必須在
該檔沒有在使用時才能進行. (比方說用救援光碟開機)
5.
結論
"預先連結"可以大大地增進一些大型應用程式的啟動時間.
Portage 也有內建的支援. "預先連結"也很安全, 發生問題的時候您可以還原任何的執行檔.
您只要記得當更新了 glibc 或其它有被"預先連結"到的函式庫時必須重新執行
prelink. 總之最後, 祝您好運!
這份文件是以
Creative Commons - 姓名標示-相同方式分享 授權條款發布
|