一、公約
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 列表
動態鏈結庫DLL
函式和資料被編譯進乙個二進位制檔案 通常擴充套件名為.lib 靜態庫 在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其它模組組合起來建立最終的可執行檔案 exe檔案 在多個同樣的程式執行時,系統保留了許多重複的 副本,造成記憶體資源浪費。動態庫 使用...
DLL(動態鏈結庫)程式設計
dll是現在常見的檔案,它整合了程式的很多功能在裡面。一般情況下,它不能直接被執行,常見的使用方法是用其他的 exe呼叫其執行,以使其內部功能表現出來。還有 ocx檔案也與之類似,也就是人們常說的com 1.簡要 windows api中所有的函式都包含在dll中,其中有3個最重要的dll。1 ke...
DLL 動態鏈結庫 專題
windows api中所有的函式都包含在dll中,其中有3個最重要的dll。1 kernel32.dll 它包含那些用於管理記憶體 程序和執行緒的函式,例如createthread函式 2 user32.dll 它包含那些用於執行使用者介面任務 如視窗的建立和訊息的傳送 的函式,例如createw...