Linux下靜態連結和動態連結程式庫的區別和建立

來源:互聯網
上載者:User
來源:http://blog.csdn.net/lwhsyit 一、引言

    

通常情況下,對函數庫的連結是放在編譯時間期(compile time)完成的。所有相關的對象檔案

(object file)與牽涉到的函數庫(library)被連結合成一個可執行檔

(executable file)。程式
在運行
時,與函數庫再無瓜葛。這些函數庫被成為靜態庫(static libaray),通常檔案

名為“libxxx.a”的形式。
    

我們也可以把對一些庫函數的連結載入延遲到程式啟動並執行時期(runtime)。這就是動態連結程式庫(dynamic link library)技術。

二、動態連結程式庫的特點與優勢

    

1. 可以實現進程之間的資源共用

     某個程式的在運行中要調用某個動態連結程式庫函數的時候,作業系統
首先會查看所有正在啟動並執行程式,看在記憶體
裡是否已有此庫函數的拷貝了。如果有,則讓其共用那一個拷貝,只有沒有才連結載入。這樣的模式雖然會帶來一些“動態連結”額外的開銷,卻大大的節省了系統

的記憶體

資源。C的標準庫就是動態連結程式庫,也就是說系統

中所有啟動並執行程式共用著同一個C標準庫的程式碼片段。

    

2. 將一些程式升級變得簡單

     使用者只需要升級動態連結程式庫,而無需重新編譯連結其他原有的代碼就可以完成整個程式的升級。Windows 就是一個很好的例子。

    

3. 甚至可以真正做到連結載入完全由程式員在程式碼中控制
    

程式員在編寫程式的時候,可以明確的指明什麼時候或者什麼情況下,連結載入哪個動態連結程式庫函數。你可以有一個相當大的軟體

,但每次啟動並執行時候,由於不同的操作需求,只有一小部分程式被載入記憶體。所有的函數本著“有需求才調入”的原則,於是大大節省了系統資源。比如現在的軟體

通常都能開啟若干種不同類型的檔案,這些讀寫操作通常都用動態連結程式庫來實現。在一次運行當中,一般只有一種類型的檔案將會被開啟。所以直到程式知道檔案的類型以後再載入相應的讀寫函數,而不是一開始就將所有的讀寫函數都載入,然後才發覺在整個程式中根本沒有用到它們。

三、動態連結程式庫的建立

    由於動態連結程式庫函數的共用特性,它們不會被拷貝到可執行檔中。在編譯的時候,編譯器只會做一些函數名之類的檢查。在程式啟動並執行時候,被調用的動態連結程式庫函
數被安置在記憶體的某個地方,所有調用它的程式將指向這個程式碼片段。因此,這些代碼必須實用相對位址,而不是絕對位址。在編譯的時候,我們需要告訴編譯器,這
些對象檔案是用來做動態連結程式庫的,所以要用地址不無關代碼(Position Independent Code (PIC))。

    

對gcc編譯器,只需添加上 -fPIC 標籤,如:

    

gcc -fPIC -c file1.c
    

gcc -fPIC -c file2.c
    

gcc -shared libxxx.so file1.o file2.o

    注意到最後一行,-shared 標籤告訴編譯器這是要建立動態連結程式庫。這與靜態連結庫的建立很不一樣,後者用的是 ar 命令

。也注意到,動態連結程式庫的名字形式為 “libxxx.so” 尾碼名為 “.so”

    如果是C++程式,注意在標頭檔函式宣告前面加上extern "C"標記,在標頭檔加上如下標記:
#ifdef __cplusplus<br />#extern "C"{<br />#endif<br />...<br />標頭檔主體<br />...<br />#ifdef __cplusplus<br />}<br />#endif 
如果不加以上標記,經過編譯後,so裡的函數名並非你編寫程式時設定的函數名

四、動態連結程式庫的使用

    

使用動態連結程式庫,首先需要在編譯期間讓編譯器檢查一些文法與定義。
    

這與靜態庫的實用基本一樣,用的是 -Lpath 和 -lxxx 標籤。如:

gcc file1.o file2.o -Lpath -lxxx -o program.exe
    

編譯器會先在path檔案夾下搜尋libxxx.so檔案,如果沒有找到,繼續搜尋libxxx.a(靜態庫)。
     在程式運行期間,也需要告訴系統去哪裡找你的動態連結程式庫檔案。在UNIX下是通過定義名為 LD_LIBRARY_PATH 的環境變數來實現的。只需將path賦值給此變數即可:export LD_LIBRARY_PATH your/full/path/to/dll
     一切安排妥當後,你可以用 ldd 命令檢查是否串連正常:ldd program.exe

     當然如果有root許可權的話,可以修改/etc/ld.so.conf檔案,然後調用 /sbin/ldconfig來達到同樣的目的,不過如果沒有root許可權,那麼只能採用輸出LD_LIBRARY_PATH的方法了。

五、注意

     調用動態庫的時候有幾個問題會經常碰到,有時,明明已經將庫的標頭檔所在目錄 通過 “-I” include進來了,庫所在檔案通過
“-L”參數引導,並指定了“-l”的庫名,但通過ldd命令察看時,就是死活找不到你指定連結的so檔案,這時你要作的就是通過修改LD_LIBRARY_PATH或者/etc/ld.so.conf檔案來指定動態庫的目錄。通常這樣做就可以解決庫無法連結的問題了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.