linux 共用庫基本使用

來源:互聯網
上載者:User

1 建立和使用靜態庫
建立一個靜態庫是相當簡單的。通常使用 ar 程式把一些目標檔案(.o)組合在一起,
成為一個單獨的庫,然後運行 ranlib,以給庫加入一些索引資訊。

2 建立和使用共用庫
特殊的編譯和串連選項
-D_REENTRANT         使得前置處理器符號 _REENTRANT 被定義,這個符號啟用一些宏特性。
-fPIC                選項產生位置獨立的代碼。由於庫是在啟動並執行時候被調入,因此這個
                     選項是必需的,因為在編譯的時候,裝入記憶體的地址還不知道。如果
                     不使用這個選項,庫檔案可能不會正確運行。
-shared              選項告訴編譯器產生共用庫代碼。
-Wl,-soname          -Wl 告訴編譯器將後面的參數傳遞到連接器。而 -soname 指定了
                     共用庫的 soname。

    # 可以把庫檔案拷貝到 /etc/ld.so.conf 中列舉出的任何目錄中,並以
root 身份運行 ldconfig;或者
    # 運行 export LD_LIBRARY_PATH='pwd',它把當前路徑加到庫搜尋路徑中去。

1.7.9  使用進階共用庫特性
1. ldd 工具
ldd 用來顯示執行檔案需要哪些共用庫, 共用庫裝載管理器在哪裡找到了需要的共用庫.

2. soname

共用庫的一個非常重要的,也是非常難的概念是 soname——簡寫共用目標名(short for shared object name)。這是一個為共用庫(.so)檔案而內嵌在控制資料中的名字。如前面提到的,每一個程式都有一個需要使用的庫的清單。這個清單的內容是一系列庫的 soname,如同 ldd 顯示的那樣,共用庫裝載器必須找到這個清單。
soname 的關鍵功能是它提供了相容性的標準。當要升級系統中的一個庫時,並且新庫的 soname 和老的庫的 soname 一樣,用舊庫串連產生的程式,使用新的庫依然能正常運行。這個特性使得在 Linux 下,升級使用共用庫的程式和定位錯誤變得十分容易。
在 Linux 中,應用程式通過使用 soname,來指定所希望庫的版本。庫作者也可以通過保留或者改變 soname 來聲明,哪些版本是相互相容的,這使得程式員擺脫了共用庫版本衝突問題的困擾。
查看/usr/local/lib 目錄,分析 MiniGUI 的共用庫檔案之間的關係

3. 共用庫裝載器

當程式被調用的時候,Linux 共用庫裝載器(也被稱為動態連接器)也自動被調用。它的作用是保證程式所需要的所有適當版本的庫都被調入記憶體。共用庫裝載器名字是 ld.so 或者是 ld-linux.so,這取決於 Linux libc 的版本,它必須使用一點外部互動,才能完成自己的工作。然而它接受在環境變數和設定檔中的配置資訊。
檔案 /etc/ld.so.conf 定義了標準系統庫的路徑。共用庫裝載器把它作為搜尋路徑。為了改變這個設定,必須以 root 身份運行 ldconfig 工具。這將更新 /etc/ls.so.cache 檔案,這個檔案其實是裝載器內部使用的檔案之一。

可以使用許多環境變數控制共用庫裝載器的操作(表1-4+)。

                        表 1-4+ 共用庫裝載器環境變數
變數                       含義
LD_AOUT_LIBRARY_PATH       除了不使用 a.out 二進位格式外,與 LD_LIBRARY_PATH 相同。
LD_AOUT_PRELOAD            除了不使用 a.out 二進位格式外,與 LD_PRELOAD 相同。
LD_KEEPDIR                 只適用於 a.out 庫;忽略由它們指定的目錄。
LD_LIBRARY_PATH            將其他目錄加入庫搜尋路徑。它的內容應該是由冒號
                           分隔的目錄列表,與可執行檔的 PATH 變數具有相同的格式。
                           如果調用設定使用者識別碼 或者進程 ID 的程式,該變數被忽略。
LD_NOWARN                  只適用於 a.out 庫;當改變版本號碼是,發出警告資訊。
LD_PRELOAD                 首先裝入使用者定義的庫,使得它們有機會覆蓋或者重新定義標準庫。
                           使用空格分開多個入口。對於設定使用者識別碼 或者進程 ID 的程式,
                           只有被標記過的庫才被首先裝入。在 /etc/ld.so.perload 中指定
                           了全域版本號碼,該檔案不遵守這個限制。
4. 使用 dlopen

    另外一個強大的庫函數是 dlopen()。該函數將開啟一個新庫,並把它裝入記憶體。該函數主要用來載入庫中的符號,這些符號在編譯的時候是不知道的。比如 Apache Web 服務器利用這個函數在運行過程中載入模組,這為它提供了額外的能力。一個設定檔控制了載入模組的過程。這種機制使得在系統中添加或者刪除一個模組時,都不需要重新編譯了。
    可以在自己的程式中使用 dlopen()。dlopen() 在 dlfcn.h 中定義,並在 dl 庫中實現。它需要兩個參數:一個檔案名稱和一個標誌。檔案名稱可以是我們學習過的庫中的 soname。標誌指明是否立刻計算庫的依賴性。如果設定為 RTLD_NOW 的話,則立刻計算;如果設定的是 RTLD_LAZY,則在需要的時候才計算。另外,可以指定 RTLD_GLOBAL,它使得那些在以後才載入的庫可以獲得其中的符號。
    當庫被裝入後,可以把 dlopen() 返回的控制代碼作為給 dlsym() 的第一個參數,以獲得符號在庫中的地址。使用這個地址,就可以獲得庫中特定函數的指標,並且調用裝載庫中的相應函數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.