More Related Content Similar to 程式設計師的自我修養 Chapter 8 (20) 程式設計師的自我修養 Chapter 82. 本章概述
● 共用程式庫的不相容更新 -> SO-NAME
● SO-NAME無法解決Minor-revision
Rendezvous Problem -> 符號版本機制和範圍
機制
● 共用程式庫的搜尋路徑
○ 標準路徑
○ 外部改變的方法
● 共用程式庫的建立和安裝
3. 共用程式庫版本
● ABI(Application Binary Interface)不相容更新
函式呼叫的堆疊結構,符號命名,參數規則
● C︰
○ 呼叫函式產生的結果不一樣
○ 匯出函式被刪除
○ 匯出資料的結構發生變化
○ 介面改變,如回傳值、參數被更新
● C++︰
○ blah...
○ blah...blah...
○ blah...blah...blah...
○ blah...blah...blah...blah...
4. 共用程式庫版本命名﹙規則﹚
● libname.so.x.y.z
○ name -->程式庫﹙又稱連結﹚名稱
○ x,主版本序號
不同主版本序號的程式庫之間是不相容的
○ y,次版本序號
增加一些新的介面符號且原來的符號不變
○ z,發行版本序號
錯誤的修正、效能的改進
● 還是有例外,Glibc
ld-x.y.z.so
5. SO-NAME
● 記錄共用程式庫依賴關係的機制
● 一般來說,去掉次版本序號和發生版本序號即
為共用程式庫所對應的SO-NAME
○ libfoo.so.2.6.1 -> libfoo.so.2
● 把SO-NAME記錄在ELF檔中,建立以SO-
NAME為名的軟式連結至系統中最新版的共用
程式庫以提升相容性
● 用ldconfig更新系統的軟式連結
● gcc -static -lglib-2.0 --> libglib-2.0.a
● gcc -Bdynamic -lglib-2.0 --> libglib-2.0.so
6. 符號版本
● 系統中只有低次版本序號的共用程式庫,就會
發生次版本序號交會問題(Minor-revision
Rendezvous Problem)
○ SO-NAME無法解決
● GLibc自2.1開始支援符號版本機制(Symbol
Versioning)
● 每個匯出和匯入的符號都有一個相關聯的版
本序號
7. Solaris中的符號版本機制
● 版本機制(Versioning)
SUNW_1.1 { SUNprivate { SUNW_1.2 {
global: global: global:
pop; __pop; swap;
push; __push; } SUNW_1.
} local: 1;
*;
}
● 範圍機制(Scoping)
對C語言來說是一個符號可見範圍的補救措施
● 編譯時,記錄實際用到最高版本符號到可執行
檔內
9. 共用程式庫系統路徑
● FHS(File Hierarchy Standard)標準規定了一
個系統中的系統檔案應該如何存放,一個系統
中主要有3個存放共用程式庫的位置︰
a. /lib存放系統最關鍵和基礎的共用程式庫
b. /usr/lib存放非系統執行時所需要的關鍵性共用程式庫
c. /usr/local/lib存放第三方應用程式的程式庫
10. 共用程式庫搜尋過程
● 如果DT_NEED保存的是絕對路徑,LD就按照
這路徑去搜尋。
● 否則﹙絕對路徑﹚, 就在/lib,/usr/lib,
/etc/ld.so.conf組態檔指定的目錄中搜尋
● 每次都搜尋全部的目錄太累了
● ldconfig幫你產生一個/etc/ld.so.cache其中
包含所有共用程式庫目錄下的共用程式庫的
SO-NAME﹙即符號連結﹚
ldconfig -p
● 如果在/etc/ld.so.cache裡找不到,再去/lib,
/usr/lib找
11. 環境變數
● LD_LIBRARY_PATH可以改變共用程式庫搜
尋路徑,優先搜尋由LD_LIBRARY_PATH指定的
目錄
LD_LIBRARY_PATH=/home/user bin/ls
/lib/ld-linux.so.2 -library-path /home/user /bin/ls
● LD_PRELOAD指定的檔案,不論使用與否都
會載入,且,會覆蓋後面載入的同名全域符
號。
● LD_DEBUG可打開LD的除錯功能
12. 共用程式庫的建立和安裝 (1/2)
● 建立
# 不要使用-fomit-frame-pointer,原因請參照函式與堆疊
gcc -shared -Wl,-soname,$(my_soname) -o $(library_name)
$(source_files)
● 測試
# 指定目的程式的共用程式庫搜尋路徑,用LD_LIBRARY_PATH更方便
ld -rpath /home/mylib -o program.out program.o -
lsomelib
● 清除符號
strip $(library_name)
ld -s/-S (所有符號資訊/除錯符號資訊)
● 安裝
ldconfig -n $(shared_library_directory)
13. 共用程式庫的建立和安裝 (2/2)
● 共用程式庫的建構式/解構式(與-nostartfiles
和-nostdlib互斥),優先順序1->n n->1
__attribute__((constructor(1)))
__attribute__((constructor(10)))
__attribute__((destructor(10)))
__attribute__((destructor(1)))
● 共用程式庫腳本
GROUP (/lib/libc.so.6 /lib/libm.so2)
14. 知道這些後我可以做什麼?
● 瞭解API/ABI backward compatible
○ SO-NAME
○ 萬不得已時,符號多載
● 看懂autotool中常見的名詞,如︰rpath
● 改變載入的過程,
○ LD_LIBRARY_PATH測試系統中新版函式庫
○ LD_PRELOAD覆寫third-party library來除錯
○ LD_DEBUG確定連結正確的shared library
● 改善程式載入速度﹙加快shared library搜
尋過程﹚