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

发布于 2024-08-17 07:54:36 字数 39 浏览 13 评论 0原文

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

When loading programs into memory, what is the difference between load-time dynamic linking and run-time dynamic linking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我家小可爱 2024-08-24 07:54:36

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

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

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

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

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

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

在 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 文件)在加载时。它可能已经在内存中包含了该库。

load-time linking is when symbols in the library, referenced by the executable (or another library) are handled when the executable/library is loaded into memory, by the operating system.

Run-time linking is when you use an API provided by the OS or through a library to load a DLL or DSO when you need it, and perform the symbol resolution then.

I know more about Linux DSOs than Windows DLL's but the principle should be the same. .NET libraries may differ.

In linux, plugin architectures are done this way. Your program will use runtime linking to load up a library and call some functions. Then maybe unload it. It also allows multiple libraries with the same symbols exported to be loaded without clashing. I think DLLs will work in much the same manner.

Executables have "blank spaces" in their symbol tables that need filling by some library. These blank-spaces are usually filled in at load-time, or compile time. You can negate the need for "blank spaces" in the symbol table by using runtime linking.

Another scenario where runtime linking is useful is for debugging libraries, or selecting from multiple, ABI/API compatible libraries at runtime. I often have a library, say "foo" and one called "foo_unstable" and have a test app that switches between the 2 and does some testing.

Under linux, to see what libraries an executable links to at load-time you run the ldd command and get output such as (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

The operating system will attempt to load the libraries (the .so files) at load-time. It may already have the library in memory.

九局 2024-08-24 07:54:36

Aiden Bell 介绍了基础知识,但我要补充一点:

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

运行时链接用于更动态的功能,例如插件加载。正如 Aiden 所说,您可以使用 LoadLibrary() 或等效方法在运行时主动将模块附加到您的程序,也许可以通过询问包含插件 DLL 的目录,依次加载每个插件并使用自制的库与它对话。插件 API。通过这样做,您的程序可以加载在编译/链接应用程序时甚至不存在的模块,因此可以在部署后有机增长。

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

Aiden Bell covered the fundamentals, but I'll add:

Load time dynamic linking is usually accomplished by statically linking your application to a .lib or .a file that contains the code for automatically establishing runtime links to symbols to be found in .dll or .so files at program startup. This is usually for fixed functionality (i.e. the C runtime library, etc.) and allows your program to reap the benefits of bug fixes in the libraries while keeping executable size small (by factoring common code into a single library).

Runtime linking is used for more dynamic functionality such as plugin loading. As Aiden said, you use LoadLibrary() or the equivalent to actively attach modules to your program at runtime, perhaps by interrogating a directory containing plugin DLLs, loading each one in turn and talking to it with a homegrown plugin API. By doing so, your program can load modules that did not even exist when your app was compiled/linked, and can thus grow organically after deployment.

Fundamentally both methods end up invoking the LoadLibrary() API, but using a fixed set of symbols and libraries in the former case and a more dynamic set in the latter.

故事未完 2024-08-24 07:54:36

距离提问已经过去很长时间了。艾登和德鲁的回答涵盖了大部分要点。我只是想从程序员的角度添加一些内容。

如果您使用加载时动态链接,我们必须链接到 LIB 文件。然后在代码中,我们可以像平常一样显式地调用该方法。 (请参阅使用加载时动态链接对于代码示例)

如果您使用运行时动态链接,则必须自己管理 DLL 加载/释放以及函数查找。 (请参阅使用运行时动态链接对于代码示例)

要在 2 个选项之间进行选择,请检查确定哪个使用的链接方法

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

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

It has been a long time since the question was asked. And Aiden and Drew's answers covered most of the essence. I just want to add a few things from a programmer's perspective.

If you use Load-Time Dynamic Linking, we have to link to the LIB file. And then in the code, we can call the method as explicitly as usual. (See Using Load-Time Dynamic Linking for the code sample)

If you use Run-Time Dynamic Linking, you have to manage the DLL loading/freeing, and function lookup yourself. (See Using Run-Time Dynamic Linking for the code sample)

For a choice between the 2 options, check Determining Which Linking Method to Use.

So, I think the Load-Time Dynamic Linking is just another way to save programmers' effort. But it comes at the price of some extensibility. You can only use the DLL corresponding to the LIB files you use as the import library.

Fundamentally, both linking approaches use the LoadLibrary() API on Windows platform.

夜光 2024-08-24 07:54:36

加载时通过创建距 DLL 开头的固定偏移量来提前优化 GetProcAddress()。较旧的可执行文件无法与较新的 DLL 一起使用,这违反了 SOLID 的开放原则;较新的可执行文件无法与较旧的 DLL 一起使用,因为函数偏移量可能不同,因此违反了 SOLID 的关闭原则。当你违反 SOLID 时,你就会陷入 DLL-HELL。

运行时无法过早优化 GetProcAddress() 调用。较旧的可执行文件可以与较新的 DLL 一起使用,但不能使用遵循 SOLID 封闭原则的新函数;较新的可执行文件可以与较旧的 DLL 一起使用,但不能使用遵循 SOLID 封闭原则的新函数。使用较旧的可执行文件与较旧的 DLL 以及使用较新的可执行文件与较新的 DLL 的比较是对 SOLID 开放原则的遵守。

热代码重载面向对象编程。如果较新的 DLL 无法与较旧的可执行文件一起使用,或者较旧的 DLL 无法与较新的可执行文件一起使用,则您违反了里氏替换原则。新版本是旧版本的继承,无论它们是可执行文件还是 DLL。

Load Time premature optimize away the GetProcAddress() by creating a fixed offset from the start of the DLL. Older executables cannot work with newer DLLs violating the Open Principle of SOLID; newer executables cannot work with older DLLs because the function offset may be different so it violates the Close Principle of SOLID. You get DLL-HELL when you violate SOLID.

Run Time cannot premature optimize away the GetProcAddress() calls. Older executables could work with newer DLLs, but cannot use the new functions adhering to the Close Principle of SOLID; newer executables could work with older DLLs, but cannot use the new functions adhering to the Close Principle of SOLID. The comparison of using older executables with older DLLs, and using newer executables with newer DLLs is the adherence of the Open Principle of SOLID.

Hot Code Reloading is Object Oriented Programming. You fail Liskov Substitution Principle where the newer DLL cannot be used with an older executable, or where the older DLL cannot be used with a newer executable. Newer versions are inheritance of older versions regardless if they are executables or DLLs.

夏夜暖风 2024-08-24 07:54:36

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

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

In load-time dynamic linking executable is linked to the DLL Library while in Runtime dynamic linking no executable was linked o any DLL.

Runtime dynamic linking is preferable when the startup performance of the application is important

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文