加载时动态链接和运行时动态链接之间的区别

时间:2010-01-13 10:09:23

标签: dll operating-system linker loader toolchain

将程序加载到内存时,加载时动态链接和运行时动态链接有什么区别?

5 个答案:

答案 0 :(得分:18)

加载时链接是指操作系统将可执行文件/库加载到内存时处理可执行文件(或其他库)引用的库中的符号。

运行时链接是指当您使用OS提供的API或通过库在需要时加载DLL或DSO,然后执行符号解析。

我对Linux DSO的了解比Windows DLL更多,但原理应该是相同的。 .NET库可能有所不同。

在linux中,插件架构就是这样完成的。您的程序将使用运行时链接来加载库并调用某些函数。然后可能卸载它。它还允许加载具有相同符号导出的多个库而不会发生冲突。我认为DLL的工作方式大致相同。

可执行文件的符号表中有“空格”,需要通过某些库填充。这些空格通常在加载时或编译时填充。您可以通过使用运行时链接来否定符号表中对“空格”的需要。

运行时链接有用的另一种情况是调试库,或者在运行时从多个ABI / API兼容库中进行选择。我经常有一个库,比如“foo”和一个名为“foo_unstable”的库,并且有一个测试应用程序可以在2之间切换并进行一些测试。

在linux下,要查看可执行文件在加载时链接到哪些库,请运行ldd命令并获取输出,如(on / 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文件)。它可能已经在内存中有了库。

答案 1 :(得分:14)

Aiden Bell介绍了基本面,但我会补充说:

加载时动态链接通常通过将应用程序静态链接到.lib.a文件来完成,该文件包含自动建立到.dll中可找到的符号的运行时链接的代码或程序启动时的.so个文件。这通常用于固定功能(即C运行时库等),并允许您的程序从库中修复错误,同时保持可执行文件的大小(通过将公共代码分解到单个库中)。

运行时链接用于更多动态功能,例如插件加载。正如Aiden所说,您可以使用LoadLibrary()或等效项来在运行时将模块主动附加到您的程序,可能是通过查询包含插件DLL的目录,依次加载每个模块并使用自行开发的插件API与之交谈。通过这样做,您的程序可以加载在编译/链接应用程序时甚至不存在的模块,并且因此可以在部署后以有机方式增长。

从根本上说,这两种方法最终都会调用LoadLibrary() API,但在前一种情况下使用一组固定的符号和库,在后一种情况下使用更动态的一组。

答案 2 :(得分:11)

问题问题已经很长时间了。 Aiden和Drew的答案涵盖了大部分内容。我只是想从程序员的角度添加一些东西。

如果使用Load-Time动态链接,我们必须链接到LIB文件。然后在代码中,我们可以像往常一样明确地调用该方法。 (有关代码示例,请参阅Using Load-Time Dynamic Linking

如果使用运行时动态链接,则必须自行管理DLL加载/释放和函数查找。 (有关代码示例,请参阅Using Run-Time Dynamic Linking

要在两个选项之间进行选择,请选中Determining Which Linking Method to Use

所以,我认为加载时动态链接只是另一种节省程序员的方法。努力。但它的代价是一些可扩展性。您只能使用与用作导入库的LIB文件对应的DLL。

从根本上说,这两种链接方法都使用Windows平台上的LoadLibrary()API。

答案 3 :(得分:0)

在加载时动态链接可执行文件链接到DLL库,而在运行时动态链接没有可执行文件链接到任何DLL。

当应用程序的启动性能很重要时,最好使用运行时动态链接

答案 4 :(得分:0)

过早的加载时间通过从DLL的开头创建一个固定的偏移量来优化GetProcAddress()。较旧的可执行文件无法与较新的DLL一起使用,这违反了SOLID的开放原则。较新的可执行文件不能与较旧的DLL一起使用,因为功能偏移可能有所不同,因此违反了SOLID的“关闭原则”。违反SOLID时,您将获得DLL-HELL。

运行时不能过早优化GetProcAddress()调用。较旧的可执行文件可以使用较新的DLL,但不能使用遵循SOLID封闭原则的新功能;较新的可执行文件可以使用较旧的DLL,但不能使用遵循SOLID封闭原则的新功能。将旧的可执行文件与旧的DLL以及使用新的可执行文件与新的DLL进行比较是SOLID开放原则的坚持。

Hot Code ReloadingObject Oriented Programming。如果新的DLL无法与较旧的可执行文件一起使用,或者较旧的DLL无法与较新的可执行文件一起使用,您将在Liskov Substitution Principle上失败。新版本是旧版本的inheritance,无论它们是可执行文件还是DLL。