摘要:和luster學習在Linux創建庫函數
不兼容的函數庫
如果一個新版的函數庫要和老版本的二進制的庫不兼容
則soname需要改變
對於C語言
一共有
個基本的理由使得它們在二進制代碼上很難兼容
o
一個函數的行文改變了
這樣它就可能與最開始的定義不相符合
o
輸出的數據項改變了
o
某些輸出的函數刪除了
o
某些輸出函數的接口改變了
如果你能避免這些地方
你就可以保持你的函數庫在二進制代碼上的兼容
或者說
你可以使得你的程序的應用二進制接口(ABI
Application Binary Interface)上兼容
動態加載的函數庫Dynamically Loaded (DL) Libraries
動態加載的函數庫Dynamically loaded (DL) libraries是一類函數庫
它可以在程序運行過程中的任何時間加載
它們特別適合在函數中加載一些模塊和plugin擴展模塊的場合
因為它可以在當程序需要某個plugin模塊時才動態的加載
例如
Pluggable Authentication Modules(PAM)系統就是用動態加載函數庫來使得管理員可以配置和重新配置身份驗證信息
Linux系統下
DL函數庫與其他函數庫在格式上沒有特殊的區別
我們前面提到過
它們創建的時候是標准的object格式
主要的區別就是這些函數庫不是在程序鏈接的時候或者啟動的時候加載
而是通過一個API來打開一個函數庫
尋找符號表
處理錯誤和關閉函數庫
通常C語言環境下
需要包含這個頭文件
Linux中使用的函數和Solaris中一樣
都是dlpoen() API
當時不是所有的平台都使用同樣的接口
例如HP
UX使用shl_load()機制
而Windows平台用另外的其他的調用接口
如果你的目的是使得你的代碼有很強的移植性
你應該使用一些wrapping函數庫
這樣的wrapping函數庫隱藏不同的平台的接口區別
一種方法是使用glibc函數庫中的對動態加載模塊的支持
它使用一些潛在的動態加載函數庫界面使得它們可以誇平台使用
具體可以參考tml
另外一個方法是使用libltdl
是GNU libtool的一部分
可以進一步參考CORBA相關資料
dlopen()
dlopen函數打開一個函數庫然後為後面的使用做准備
C語言原形是
void * dlopen(const char *filename
int flag);
如果文件名filename是以
/
開頭
也就是使用絕對路徑
那麼dlopne就直接使用它
而不去查找某些環境變量或者系統設置的函數庫所在的目錄了
否則dlopen()
就會按照下面的次序查找函數庫文件
環境變量LD_LIBRARY指明的路徑
/etc/ld
so
cache中的函數庫列表
/lib目錄
然後/usr/lib
不過一些很老的a
out的loader則是采用相反的次序
也就是先查/usr/lib
然後是/lib
Dlopen()函數中
參數flag的值必須是RTLD_LAZY或者RTLD_NOW
RTLD_LAZY的意思是resolve undefined symbols as code from the dynamic library is executed
而RTLD_NOW的含義是resolve all undefined symbols before dlopen() returns and fail if this cannot be done
如果有好幾個函數庫
它們之間有一些依賴關系的話
例如X依賴Y
那麼你就要先加載那些被依賴的函數
例如先加載Y
然後加載X
dlopen()函數的返回值是一個句柄
然後後面的函數就通過使用這個句柄來做進一步的操作
如果打開失敗dlopen()就返回一個NULL
如果一個函數庫被多次打開
它會返回同樣的句柄
如果一個函數庫裡面有一個輸出的函數名字為_init
那麼_init就會在dlopen()這個函數返回前被執行
我們可以利用這個函數在我的函數庫裡面做一些初始化的工作
我們後面會繼續討論這個問題的
dlerror()
通過調用dlerror()函數
我們可以獲得最後一次調用dlopen()
dlsym()
或者dlclose()的錯誤信息
From:http://tw.wingwit.com/Article/program/Oracle/201311/16711.html