動態(tài)鏈接庫是一個可以執(zhí)行的并可以被多個Windows應用程序共享的程序模塊,模塊中包含了一些可以被多個Windows應用程序�DLL共享的代�、數(shù)據和資源�
所謂動�(tài)鏈接,就是把一些經常會共用的代碼(靜態(tài)鏈接的OBJ程序庫)制作成DLL�,當可執(zhí)行文件調用到DLL檔內的函�(shù)�,windows操作系統(tǒng)才會把DLL檔加載存儲器�,DLL檔本身的結構就是可可�(zhí)行文�,當程序需求函�(shù)才進行鏈接。通過動態(tài)鏈接方式,存儲器浪費的情形將可大幅降��
動態(tài)鏈接庫的最初目的是節(jié)約應用程序所需的磁盤和內存空間。在一個傳�(tǒng)的非共享庫中,一部分代碼簡單地附加到調用的程序上。如果兩個程序調用同一個子程序,就會出�(xiàn)兩份那段代碼。相�,許多應用共享的代碼能夠切分到一個動�(tài)鏈接庫中,在硬盤上存為一個文�,在內存中使用一個實例(instance)。動�(tài)鏈接庫的廣泛應用使得早期的視窗能夠運行在緊巴巴的內存條件��
動態(tài)鏈接庫提供了如模塊化這樣的共享庫的普通好�。模塊化允許僅僅更改幾個應用程序共享使用的一個動�(tài)鏈接庫中的代碼和�(shù)據而不需要更改應用程序自�。這種模塊化的基本形式允許如Microsoft Office、Microsoft Visual Studio、甚至微軟視窗自身這樣大的應用程序使用較為緊湊的補丁和服務��
模塊化的另外一個好處是插件的通用接口使用。單個的接口允許舊的模塊與新的模塊一樣能夠與以前的應用程序運行時無縫地集成到一起,而不需要對應用程序本身作任何更�。這種動態(tài)擴展的思想在ActiveX中發(fā)揮到了�
盡管有這么多的�(yōu)�,使用動�(tài)鏈接庫也有一個缺點:動態(tài)鏈接庫地獄,也就是幾個應用程序在使用同一個共享動�(tài)鏈接庫庫�(fā)生版本沖�。這樣的沖突可以通過將不同版本的問題動態(tài)鏈接庫放到應用程序所在的文件夾而不是放到系�(tǒng)文件夾來解決;但�,這樣將抵消共享動�(tài)鏈接庫節(jié)約的空間。目�,Microsoft .NET將解決動�(tài)鏈接� hell問題當作自己的目�,它允許同一個共享庫的不同版本并列共存。由于現(xiàn)代的計算機有足夠的磁盤空間和內存,這也可以作為一個合理的實現(xiàn)方法�
內存管理
在Win32�,DLL文檔按照片段(sections)進行組織。每個片段有它自己的屬�,如可寫或是只讀、可�(zhí)行(代碼)或者不可執(zhí)行(�(shù)據)等等�
DLL代碼段通常被使用這個DLL的進程所共享;也就是說它們在物理內存中占據一個地�,并且不會出�(xiàn)在頁面文檔中。如果代碼段所占據的物理內存被收回,它的內容就會被放棄,后面如果需要的話就直接從DLL文檔重新加載�
與代碼段不同,DLL的數(shù)據段通常是私有的;也就是�,每個使用DLL的進程都有自己的DLL�(shù)據副本。作為選�,數(shù)據段可以設置為共享,允許通過這個共享內存區(qū)域進行進程間通信。但�,因為用戶權限不能應用到這個共享DLL內存,這將產生一個安全漏�;也就是一個進程能夠破壞共享�(shù)�,這將導致其它的共享進程異常。例如,一個使用訪客賬號的進程將可能通過這種方式破壞其它運行在特權賬號的進程。這是在DLL中避免使用共享片段的一個重要原��
當DLL被如UPX這樣一個可�(zhí)行的packer壓縮�,它的所有代碼段都標記為可以讀寫并且是非共享的??梢宰x寫的代碼�,類似于私有�(shù)據段,是每個進程私有的并且被頁面文檔備份。這樣,壓縮DLL將同時增加內存和磁盤空間消耗,所以共享DLL應當避免使用壓縮DLL�
符號解析和綁�
DLL輸出的每個函�(shù)都由一個數(shù)字序號標識,也可以由可選的名字標�。同樣,DLL引入的函�(shù)也可以由序號或者名字標�。對于內部函�(shù)來說,只輸出序號的情形很常見。對于大多數(shù)視窗API函數(shù)來說名字是不同視窗版本之間保留不變的;序號有可能會發(fā)生變�。這樣,我們不能根據序號引用視窗API函數(shù)�
按照序號引用函數(shù)并不一定比按照名字引用函數(shù)性能更好:DLL輸出表是按照名字排列�,所以對半查找可以用來在在這個表中根據名字查找這個函�(shù)。另外一方面,只有線性查找才可以用于根據序號查找函數(shù)�
將一個可�(zhí)行文件綁定到一個特定版本的DLL也是可能�,這也就是�,可以在編譯時解析輸入函�(shù)(imported functions)的地址。對于綁定的輸入函數(shù),連結工具保存了輸入函�(shù)綁定的DLL的時間戳和校驗和。在運行時Windows檢查是否正在使用同樣版本的庫,如果是的話,Windows將繞過處理輸入函�(shù);否則如果庫與綁定的庫不�,Windows將按照正常的方式處理輸入函數(shù)�
綁定的可�(zhí)行文件如果運行在與它們編譯所用的�(huán)境一�,函�(shù)調用將會較快,如果是在一個不同的�(huán)境它們就等同于正常的調用,所以綁定輸入函�(shù)沒有任何的缺點。例�,所有的標準Windows應用程序都綁定到它們各自的Windows�(fā)布版本的系統(tǒng)DLL。將一個應用程序輸入函�(shù)綁定到它的目的環(huán)境的好機會是在應用程序安裝的過程�
運行時顯式鏈�
對每個DLL來說,Windows存儲了一個全局計數(shù)器,每多一個進程使用便多額外一�。LoadLibrary與FreeLibrary指令影響每一個進程內含的計�(shù)器;動態(tài)連結則不影響。因此借由調用FreeLibrary多次,從存儲器反加載一DLL是很重要�。一個進程可以從它自己的VAS注銷此計�(shù)��
DLL文檔能夠在運行時使用LoadLibrary(或者LoadLibraryEx)API函數(shù)進行顯式調用,這個的過程微軟簡單地稱為運行時動態(tài)調用。API函數(shù)GetProcAddress根據查找輸出名稱符號、FreeLibrary卸載DLL。這些函數(shù)類似于POSIX標準API中的dlopen、dlsym、和dlclose�
注意微軟簡單稱為運行時動�(tài)鏈接的運行時隱式鏈接,如果不能找到鏈接的DLL文檔,Windows將提示一個錯誤消息并且調用應用程序失�。應用程序開�(fā)人員不能通過編譯鏈接來處理這種缺少DLL文檔的隱式鏈接問�。另外一方面,對于顯式鏈�,開�(fā)人員有機會提供一個完善的出錯處理機制�
運行時顯式鏈接的過程在所有語言中都是相同的,因為它依賴于Windows API而不是語言結構�
?�?)應用范圍廣�
?�?)便于開�(fā)大型軟件�
?�?)便于對系統(tǒng)進行升級�
?�?)隱藏細節(jié)�
?�?)獨立于編程語言�
維庫電子通,電子知識,一查百通!
已收錄詞�156117�