2010-01-13 413 views

回答

17

加載時鏈接是操作系統將可執行文件(或其他庫)引用的庫中的符號處理爲可執行文件/庫加載到內存中時的加載時鏈接。

運行時鏈接是指當您使用OS提供的API或通過庫在需要時加載DLL或DSO並執行符號解析時。

我對Linux DSO的瞭解比Windows DLL更多,但原理應該是一樣的。 .NET庫可能會有所不同。

在linux中,插件體系結構是這樣完成的。你的程序將使用運行時鏈接加載一個庫並調用一些函數。然後可能卸載它。它還允許導出相同符號的多個庫在不衝突的情況下加載。我認爲DLL的工作方式大致相同。

可執行文件的符號表中有「空格」,需要由某個庫填充。這些空白空間通常在加載時或編譯時填充。您可以通過使用運行時鏈接來避免在符號表中需要「空格」。

運行時鏈接有用的另一種場景是用於調試庫或在運行時從多個ABI/API兼容庫中進行選擇。我經常有一個圖書館,說「富」,一個名爲「foo_unstable」,並有一個測試應用程序之間切換2並做一些測試。

在Linux下,看到在加載時哪些庫可執行文件鏈接到您運行ldd命令,並得到輸出,如(依賴/ bin/LS):

linux-vdso.so.1 => (0x00007fff139ff000) 
librt.so.1 => /lib64/librt.so.1 (0x0000003c4f200000) 
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003c4fa00000) 
libcap.so.2 => /lib64/libcap.so.2 (0x0000003c53a00000) 
libacl.so.1 => /lib64/libacl.so.1 (0x0000003c58e0000 

操作系統將嘗試在加載時加載庫(.so文件)。它可能已經在內存中擁有庫。

14

艾登貝爾覆蓋的基本面,但我會補充:通過您的應用程序靜態鏈接到包含自動建立運行時的鏈接符號的代碼.lib.a文件

加載時動態鏈接通常是完成請在程序啓動時在.dll.so文件中找到。這通常用於固定功能(即C運行時庫等),並允許程序在保持可執行文件較小(通過將通用代碼分解到單個庫中)的同時獲得庫中錯誤修復的好處。

運行時鏈接用於更多動態功能,如插件加載。正如Aiden所說的,你可以使用LoadLibrary()或者等價的方法在運行時主動附加模塊到你的程序中,也許通過詢問一個包含插件DLL的目錄,依次加載每一個目錄,並用一個本土的插件API與之交談。通過這樣做,您的程序可以加載在編譯/鏈接應用程序時甚至不存在的模塊,並且可以在部署後有機地增長。

從根本上說,兩種方法最終都會調用LoadLibrary() API,但在前一種情況下使用一組固定的符號和庫,在後者中使用一組固定的符號和庫。

+2

+1可帶來開發/增長優勢。模塊化架構很酷。 – 2010-01-13 10:54:08

+2

.Net可執行文件的其他信息:它們使用運行時動態鏈接。如果您在「Dependency Walker」中打開.Net DLL,您可以看到它們只與MSCOREE.DLL進行加載時動態鏈接。與此相關的更多信息在這裏:http://stackoverflow.com/questions/9545603/is-mscorlib-dll-mscoree-dll-loaded-when-net-application-runs如果你參考但不使用DLL和DLL丟失,那麼你的應用程序不會錯誤。您可以在Debug> Windows> Modules中看到當前加載的DLL。 – 2013-06-10 18:33:00

9

問自問已經很長時間了。艾登和德魯的答案涵蓋了大部分的本質。我只是想從程序員的角度添加一些東西。

如果使用加載時間動態鏈接,我們必須鏈接到LIB文件。然後在代碼中,我們可以像往常一樣明確地調用方法。 (代碼示例請參見Using Load-Time Dynamic Linking

如果使用運行時動態鏈接,則必須自己管理DLL加載/釋放和函數查找。 (有關代碼示例,請參見Using Run-Time Dynamic Linking

要選擇2個選項,請選擇Determining Which Linking Method to Use

所以,我覺得加載時動態鏈接只是另一種方式,以節省程序員的努力。但它是以一些可擴展性爲代價的。您只能使用與您用作導入庫的LIB文件相對應的DLL。

基本上,這兩種鏈接方法都使用Windows平臺上的LoadLibrary()API。

0

在加載時動態鏈接可執行文件鏈接到DLL庫,而在運行時動態鏈接沒有可執行文件鏈接到任何DLL。

當應用程序的啓動性能很重要時,運行時動態鏈接更可取