程式設計師的自我修養 Chapter 8

1,981 views
1,896 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,981
On SlideShare
0
From Embeds
0
Number of Embeds
32
Actions
Shares
0
Downloads
36
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

程式設計師的自我修養 Chapter 8

  1. 1. 程式設計師的自我修養Chapter 8 Linux共用程式庫的組織 Shu-Yu Fu
  2. 2. 本章概述● 共用程式庫的不相容更新 -> SO-NAME● SO-NAME無法解決Minor-revision Rendezvous Problem -> 符號版本機制和範圍 機制● 共用程式庫的搜尋路徑 ○ 標準路徑 ○ 外部改變的方法● 共用程式庫的建立和安裝
  3. 3. 共用程式庫版本● ABI(Application Binary Interface)不相容更新 函式呼叫的堆疊結構,符號命名,參數規則● C︰ ○ 呼叫函式產生的結果不一樣 ○ 匯出函式被刪除 ○ 匯出資料的結構發生變化 ○ 介面改變,如回傳值、參數被更新● C++︰ ○ blah... ○ blah...blah... ○ blah...blah...blah... ○ blah...blah...blah...blah...
  4. 4. 共用程式庫版本命名﹙規則﹚● libname.so.x.y.z ○ name -->程式庫﹙又稱連結﹚名稱 ○ x,主版本序號 不同主版本序號的程式庫之間是不相容的 ○ y,次版本序號 增加一些新的介面符號且原來的符號不變 ○ z,發行版本序號 錯誤的修正、效能的改進● 還是有例外,Glibc ld-x.y.z.so
  5. 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. 6. 符號版本● 系統中只有低次版本序號的共用程式庫,就會 發生次版本序號交會問題(Minor-revision Rendezvous Problem) ○ SO-NAME無法解決● GLibc自2.1開始支援符號版本機制(Symbol Versioning)● 每個匯出和匯入的符號都有一個相關聯的版 本序號
  7. 7. Solaris中的符號版本機制● 版本機制(Versioning) SUNW_1.1 { SUNprivate { SUNW_1.2 { global: global: global: pop; __pop; swap; push; __push; } SUNW_1. } local: 1; *; }● 範圍機制(Scoping) 對C語言來說是一個符號可見範圍的補救措施● 編譯時,記錄實際用到最高版本符號到可執行 檔內
  8. 8. GCC對Solaris符號版本機制的擴充● asm (".symver add, add@VERS_1.1");● 更改了介面或含義又不想更改主版本序號● asm (".symver addex, add@VERS_1.2");
  9. 9. 共用程式庫系統路徑● FHS(File Hierarchy Standard)標準規定了一 個系統中的系統檔案應該如何存放,一個系統 中主要有3個存放共用程式庫的位置︰ a. /lib存放系統最關鍵和基礎的共用程式庫 b. /usr/lib存放非系統執行時所需要的關鍵性共用程式庫 c. /usr/local/lib存放第三方應用程式的程式庫
  10. 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. 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. 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. 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. 14. 知道這些後我可以做什麼?● 瞭解API/ABI backward compatible ○ SO-NAME ○ 萬不得已時,符號多載● 看懂autotool中常見的名詞,如︰rpath● 改變載入的過程, ○ LD_LIBRARY_PATH測試系統中新版函式庫 ○ LD_PRELOAD覆寫third-party library來除錯 ○ LD_DEBUG確定連結正確的shared library● 改善程式載入速度﹙加快shared library搜 尋過程﹚

×