一、動態鏈接庫的技術優點:
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首地址與函數相對地址的和用來替換在程序中函數調用的地址指針[程序編譯鏈接后,函數調用處均為地址跳轉]。

