標籤:
一、動態連結程式庫的技術優點:
1)節省記憶體和磁碟空間;因為動態庫在記憶體或磁碟中只需一份,便可供多個進程或程式使用。
2)模組化編程,方便協作;這一點靜態庫也能勝任。
3)使用動態載入DLL或SO時,便於模組升級,無需重新編譯或連結整個程式。
二、windows的動態連結程式庫:
1.windows的靜態庫產生的是.lib檔案,其中包含了函數和資料實體,連結時合到程式中;
2.windows的動態庫產生.dll檔案並匯出一個.lib檔案,該.lib檔案中的函數沒有實體[不是一個
準確的說法],函數內部是一個跳轉,指向.dll中的函數實體;當然,在.lib中的跳轉地址是一個相對地
址[函數在dll的位移地址];而且.dll檔案是一個地址可重定位檔案。
3.動態庫的使用有兩種方法:
1)動態連結:
連結時將動態庫匯出的.lib檔案連結到可執行檔中去。
當程式載入到記憶體時,會有動態連結器將要載入的動態庫載入到記憶體[已在記憶體則不用載入],此時該.dll
記憶體位址確定,動態連結器將程式中的.lib部分中函數跳轉地址改為原來的位移地址加上該.dll起始地址的結果。
這樣就可以找到要調用的函數位置了。
至於多進程共用一個動態庫,每次動態連接器都將記憶體中的同一個庫的地址映射到不同的進程空間[虛擬記憶體];
映射到不用的進程空間的地址很可能是不同的。
2)動態載入:
即在程式啟動並執行過程中及時的將需要的庫載入進記憶體[已存在則不用載入],通過相應的API拿到需要使用的動
態庫函數介面地址,使用函數指標的方式去使用,在使用完後可以動態卸載動態庫。
(*)兩種方式對比:
(1)第一種方法需要函數、變數的申明[即C/C++中要標頭檔],並且使用.lib來"欺騙"靜態連結器;
而第二種方法沒有函式宣告,使用函數時是採取函數指標的方式,所以靜態連結器也沒辦法"找茬"。
(2)第一種方法由系統來維護動態庫載入和卸載;第二種則需要程式員自行解決。
那麼同時第一種方法該動態庫在該進程空間的生命週期與程式生命週期相同;第二種則由程式員決定。
(3)第一種在發布新的dll時,要用相應的lib檔案重新連結程式;第二種則不需要,只需替換掉舊的dll.
三、Linux的共用庫:
Linux的共用庫與windows的動態庫本質相同,特別是在動態載入時。差異主要體現在Linux的共用庫產生.so檔案時不會
同時匯出一個類似.lib的檔案。
如果要用動態連結的方法,則需要將.so檔案拿來連結時使用,不過它不會真的將該檔案連結進最終的可執行檔。它只是
記錄下依賴該.so檔案,並將引用於該.so的函數等符號記錄到需要重定位的符號列表中[列表中包含了各個函數的相對位址],
在程式載入到記憶體空間時,類似windows中,也是將確定的.so首地址與函數相對位址的和用來替換在程式中函數調用的地址指
針[程式編譯連結後,函數調用處均為地址跳轉]。
windows動態連結程式庫[DLL]與Linux共用庫[SO]技術淺析