加载时动态链接和运行时动态链接之间的区别
加载时链接是操作系统将可执行文件(或其他库)引用的库中的符号处理为可执行文件/库加载到内存中时的加载时链接。
运行时链接是指当您使用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文件)。它可能已经在内存中拥有库。
艾登贝尔覆盖的基本面,但我会补充:通过您的应用程序静态链接到包含自动建立运行时的链接符号的代码.lib
或.a
文件
加载时动态链接通常是完成请在程序启动时在.dll
或.so
文件中找到。这通常用于固定功能(即C运行时库等),并允许程序在保持可执行文件较小(通过将通用代码分解到单个库中)的同时获得库中错误修复的好处。
运行时链接用于更多动态功能,如插件加载。正如Aiden所说的,你可以使用LoadLibrary()
或者等价的方法在运行时主动附加模块到你的程序中,也许通过询问一个包含插件DLL的目录,依次加载每一个目录,并用一个本土的插件API与之交谈。通过这样做,您的程序可以加载在编译/链接应用程序时甚至不存在的模块,并且可以在部署后有机地增长。
从根本上说,两种方法最终都会调用LoadLibrary()
API,但在前一种情况下使用一组固定的符号和库,在后者中使用一组固定的符号和库。
问自问已经很长时间了。艾登和德鲁的答案涵盖了大部分的本质。我只是想从程序员的角度添加一些东西。
如果使用加载时间动态链接,我们必须链接到LIB文件。然后在代码中,我们可以像往常一样明确地调用方法。 (代码示例请参见Using Load-Time Dynamic Linking)
如果使用运行时动态链接,则必须自己管理DLL加载/释放和函数查找。 (有关代码示例,请参见Using Run-Time Dynamic Linking)
要选择2个选项,请选择Determining Which Linking Method to Use。
所以,我觉得加载时动态链接只是另一种方式,以节省程序员的努力。但它是以一些可扩展性为代价的。您只能使用与您用作导入库的LIB文件相对应的DLL。
基本上,这两种链接方法都使用Windows平台上的LoadLibrary()API。
在加载时动态链接可执行文件链接到DLL库,而在运行时动态链接没有可执行文件链接到任何DLL。
当应用程序的启动性能很重要时,运行时动态链接更可取
+1可带来开发/增长优势。模块化架构很酷。 – 2010-01-13 10:54:08
.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