Linux編程簡介——動態鏈接庫


傳統方式下,庫函數的鏈接是在編譯器完成的,所有相關對象在編譯的時候被整合成一個可執行文件。與此相比,我們也可以把對庫函數的鏈接載入推遲到程序運行的時期,也就是我們所稱作的動態鏈接。

動態鏈接的優點

除了靜態鏈接庫所有的模塊化和代碼復用外,動態鏈接庫還有如下優點。

  • 可以實現進程之間的庫共享:
    當多個進程共享一個庫時(如stl庫和一些系統庫是基本上大多數程序都用的),動態鏈接方式可以只在內存中保留一份副本,節約內存。
  • 升級變得簡單:
    用戶只需要升級動態鏈接庫,而無需重新編譯鏈接其他原有的代碼就可以完成整個程序的升級(很多Windows的補丁就是這種方式發布的)。
  • 可以動態載入:
    當軟件比較大的時候,可以根據需要動態載入/卸載相應的鏈接庫,而無需像靜態鏈接的方式那樣必須一次性全部載入

創建動態鏈接庫

創建動態鏈接庫的方式比較簡單,以前文靜態鏈接庫的例子為例,我們只需要通過gcc -shared指令即可創建一個libstack.so的動態庫(靜態庫一般以.a作為擴展名,動態庫一般以.so作為擴展名)。

    gcc -shared -o libstack.so stack.o

在鏈接階段使用動態庫的方式基本上和靜態庫一致。

    gcc -o run main.c -L. –lstack

編譯玩這個程序后,我們執行后卻發現,它報動態鏈接庫找不到的錯誤提示。

    tianfang > ./run
    ./run: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory

我們也可以通過ldd命令查看某程序當前對動態鏈接庫的依賴情況:

    tianfan > ldd run
    linux-gate.so.1 (0xb7707000)
    libstack.so => not found
    libc.so.6 => /lib/libc.so.6 (0xb7546000)
    /lib/ld-linux.so.2 (0xb7708000)

ldd的結果表明了我們生成的libstack.so找不到。因為動態鏈接庫是一個可以共享的文件,因此往往存放在一個公共的位置,在Linux系統中程序查找動態鏈接庫的規則如下:

  1. 首先在環境變量LD_LIBRARY_PATH所記錄的路徑中查找。
  2. 然后從緩存文件/etc/ld.so.cache中查找。
  3. 如果上述步驟都找不到,則到默認的系統路徑中查找,先是/lib然后是/usr/lib。

很明顯,這幾個路徑都不包含當前路徑。要解決上述問題,一個簡單的方式就是把當前路徑加到環境變量中:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

然后再次用ldd名稱測試,發現現在就能找到我們的鏈接庫了。

    tianfan > ldd run
    linux-gate.so.1 (0xb77ce000)
    libstack.so => ./libstack.so (0xb77ca000)
    libc.so.6 => /lib/libc.so.6 (0xb760a000)
    /lib/ld-linux.so.2 (0xb77cf000)

不過,很多大牛並不建議通過修改LD_LIBRARY_PATH這種方式

小結

本文主要介紹了一下如何通過gcc命令創建動態鏈接庫,如何通過ldd命令查看對動態鏈接庫的依賴情況和解決動態鏈接庫找不到的問題。並沒有對動態鏈接庫的原理進行詳細的介紹,感興趣的朋友可以在網上查找相關文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM