linux下的動態連結程式庫(DLL)__linux

來源:互聯網
上載者:User

一、公約

1. 庫的命名習慣

一個linux DLL 有三個不同名字的檔案組成

soname 檔案 lib + 連結庫名字 + .so + .版本號碼

每當連結庫介面改變時都遞增版本號碼。soname 檔案其實只是一個符號連結而已,指向他的real name 檔案。

real name 檔案 lib + 連結庫名字 + .so + .版本號碼.次版本號碼.發行號

發行號是可選的。該檔案包含實際代碼。

linker name 檔案 lib + 連結庫名字 + .so

編譯器以這個名字來請求指定的連結庫。

當程式在內部列出所需要的連結庫時,僅僅使用 soname。當你建立一個連結庫時,使用 real name。安裝一個新的連結庫時,把它複製到一個DLL檔案夾裡,然後運行程式 ldconfig(8)。ldconfig 檢查存在的 real name 檔案,並且建立指向它的符號連結 soname 檔案。ldconfig 還做一件事情就是建立 cache 檔案 /etc/ld.so.cache

ldconfig 不會建立 linker name 檔案,但是一般性 linker name 檔案在安裝連結庫的時候建立。linker name 檔案也只是一個符號連結,指向最新的 soname 檔案或 real name 檔案。建議指向 soname 檔案,因為當你更新庫以後,在編譯器連結的時候,一般總是想使用新的庫。

2. 庫的放置

DLL 必須放置在檔案系統的指定位置。多數開源軟體遵守GNU 標準:當分發原始碼的時候,庫預設安裝在 /usr/local/lib,命令安裝在 /usr/local/bin。該標準還定義了如何重寫這些預設標準以及如何調用安裝程式。

Filesystem Hierarchy Standard(FHS) 規定:多數庫應安裝在 /usr/lib,啟動時需要的庫安裝在 /lib,非系統庫應安裝在 /usr/local/lib

GNU 標準是針對開發人員的,FHS 是針對發行者的。

二、 庫是如何被使用的

在基於 GNU glibc 的系統上,包括所有 linux 系統,ELF 可執行二進位檔案的運行自動導致程式載入器被載入並且運行。在 linux 下,載入器是 /lib/ld-linux.so.X(X是版本號碼)。然後載入器搜尋、載入程式所要使用的動態連結程式庫。

被搜尋的資料夾清單儲存在檔案 /etc/ld.so.conf 裡。

在程式啟動的時候搜尋這些檔案夾是很沒有效率的,所以實際上使用緩衝。ldconfig(8) 預設讀取 /etc/ld.so.conf 檔案,在 DLL 檔案夾裡建立合適的符號連結,在 /etc/ld.so.cache 裡寫入一個緩衝。緩衝大大加速了庫的讀取。所以,當一個 DLL 被添加、刪除時,或DLL檔案夾被改變時都需要運行 ldconfig 程式,當安裝了一個新的 DLL 時,由軟體包管理器自動運行 ldconfig。當程式啟動時,裝載器實際使用的是緩衝。

環境變數

LD_LIBRARY_PATH
該變數裡所指定的檔案夾將會首先被搜尋,然後才會搜尋預設的 DLL 檔案夾。該變數對開發與測試比較有用,但不應該為了給普通使用者使用而設定。如果你不想設定該變數,在 linux 下你可以直接調用程式載入器,比如,你可以傳遞 PATH 參數給載入器代替該變數來運行程式: /lib/ld-linux.so.2 --library-path PATH EXECUTABLE

不帶參數執行載入器,可以得到更多協助。但是,不要這樣執行程式,僅供調試時使用。

LD_DEBUG
看名字就知道,是供調試使用的。該變數是dl*函數的開關,用來顯示正在做的事情的詳細資料。可以取值為:

files 顯示so檔案的載入順序
bindings 顯示關於符號幫定的資訊
libs 顯示庫搜尋路徑的資訊
versions 顯示版本依賴的資訊
help 使用該值運行程式將會顯示可用的選項


三、建立動態連結程式庫

首先用 -fpic 或 -fPIC 選項建立要放入 DLL 中的目標檔案。使用該選項產生的程式碼是位置無關的代碼(DLL的必要條件)。使用 gcc 的 -Wl 選項傳遞 soname 參數給連結器。-Wl 選項裡不能有未轉義的 whitespace。使用如下命令建立 DLL: gcc -shared -Wl,-soname,your_soname \
    -o library_name file_list library_list

舉個例子: gcc -fPIC -g -c -Wall a.c
gcc -fPIC -g -c -Wall b.c
gcc -shared -Wl,-soname,libmystuff.so.1 \
    -o libmystuff.so.1.0.1 a.o b.o -lc

該例子首先建立了兩個與位置無關的目標檔案 a.o、b.o,然後產生了一個包含兩者的 DLL。注意:-g 選項使程式碼封裝含調試資訊,-Wall 選項用來產生警告,兩者並不是建立 DLL 必須的,但是建議加上。

不要 strip 所產生的 DLL,或使用編譯器參數 -fomit-frame-pointer,這樣做將會無法使用調試器。

-fPIC 選項總是可以使用,但產生的程式碼比使用 -fpic 的要大。-fpic 選項產生的程式碼比較小、快,但是有平台相關的限制,當建立 DLL 時,連結器將會告訴你是否符合限制。

連結器還有一個有用的選項 -rpath,可以用來指定程式在運行時搜尋DLL時的路徑,使用 gcc 時可以這樣傳遞參數給連結器: -Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

如果你使用了這個選項,就不用考慮 LD_LIBRARY_PATH 這個環境變數了。

 

四、安裝、使用動態連結程式庫

1.安裝在標準位置
最簡單的安裝方式是複製 DLL 到一個標準的 DLL 檔案夾(/usr/lib等)並且運行 ldconfig(8),然後手動建立 linker name 符號連結。

2.安裝在非標準位置
下面的命令將會在指定的檔案夾裡建立適當的 soname 符號連結。 ldconfig -n directory_with_shared_libraries

然後手動建立 linker name 檔案指向 soname 檔案。


編譯器的時候使用 -l、-L 參數指定需要連結的庫和庫所在的位置。
除非使用 -rpath 參數指定過執行階段程式庫搜尋路徑,否則在運行時也必須指定。

比如可以使用如下命令添加當前工作目錄到 LD_LIBRARY_PATH 來運行程式: LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH  my_program


ldd 命令可以用來查看程式的依賴,例如: ldd /bin/ls

輸出的是 soname 列表

相關文章

聯繫我們

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