用c语言链接和加载有什么区别

链接和加载动态库是否都在运行时发生? 或者只是在运行时加载库?

请参阅前面关于静态链接和动态链接之间区别的非常好的观点。 假设您指的是动态链接,那么:

加载和(动态)链接都是由链接器完成的 – 在linux和其他Unix上/lib/ld.so ,这是由/lib/ld.so完成的,这是几乎所有情况下操作系统启动的实际程序。 ld.so反过来你的应用程序 – mygameBinary 加载到内存中,然后ld.so从文件mygameBinary读取它需要的动态链接库列表。

然后,链接器ld.so依次将每个库加载到内存中,例如libc.solibpthread.solibopengl.so ,并查看这些可能需要的其他库,例如libm.so

加载完成后,开始链接 ,查看由一个库或应用程序导出并由另一个库或应用程序导入的命名对象或函数的过程。 然后,链接器会更改各种引用,有时还会更新代码以更新每个库中未链接的数据指针和函数调用,以指向实际数据或函数所在的位置。 例如,在mygameBinaryprintfmygameBinary开始时没有指向任何内容(实际上它只是调用链接器),但是在链接之后成为跳转到libcprintf函数。

完成此链接后,通过调用mygameBinary_start函数启动应用程序,然后调用main ,然后启动游戏。

以这种方式动态链接是必要的,以支持以下内容:

  • 应用程序发布后库更新,这会更改函数和数据的位置。
  • 在不同版本的OS上运行的单个应用程序
  • 关于库或应用程序可能在内存中加载的不确定性
  • 通过在多个应用程序之间共享库使用的物理ram来减小核心的大小。

某些操作系统的细节不同,例如OSX和AIX都将某组库预加载到内存中的固定位置。 这意味着它们不需要加载,只需链接,这可能更快。

某些操作系统(如OSX,有时是Linux)支持预链接,这是一个脚本在启动它们之前在系统上的应用程序上运行并进行链接的过程。 启动它们时,您无需链接它们。 这一点非常重要,因为在启动应用程序时,链接会占用大量计算机的时间,某些应用程序可能会每秒多次启动,例如gcccpp和应用程序构建过程,或者在索引计算机数据时过滤脚本(OSX Spotlight)。

链接是将一些较小的可执行文件作为单个较大的可执行文件连接在一起的过程。

加载是在执行之前将可执行文件加载到内存中。

有两种类型的链接:静态链接和动态链接。

静态链接在编译时发生,因此它在加载程序之前发生。 使用静态链接,程序使用的外部符号(例如函数名称)将在编译时解析。

动态链接在运行时发生,因此它发生在加载程序之后或加载时。 通过动态链接,符号在加载时或在访问符号时的运行时解析(延迟绑定)。 后者更为常见。

file01.c,file02.c – >产生 – > file01.o,file02.o – >这些.o信息被分组并放入一个动态库,即lib1.a file11.c,file12.c – >产生 – > file11.o,file12.o – >这些.o信息被分组并放入一个动态库,即lib2.a

现在,我有2个库最终链接在一起以生成可执行文件(如.elf或.mot或.fls)。 将lib1.a和lib2.a中的信息链接起来形成单个可执行文件的过程称为链接。

现在,我需要将其加载到内存中以便运行它以查看最终可执行文件的行为。 将最终可执行文件(如.elf或.mot或.fls)加载到内存中以便运行的过程称为加载。

我希望这将清除链接和加载的重要性(但定义不合适:-))。

两者都在运行时发生在动态库中。

首先,加载库以及它们的所有依赖项(以及这些库的依赖项,等等)。 然后动态链接器解析加载库中的符号。 通常这两个function都是由同一个软件实现的; 在Linux上它是ld.so。

静态库中的符号在链接时解析并包含在可执行文件本身中。 但是,静态库可能具有未解析的符号,这些符号在运行时由动态库满足。

在如何编写共享库中 ,有一个深入的描述如何发生这种情况,如何对名称进行哈希处理,在运行时解析符号的成本等等。

Windows和Unix系统使用完全不同的动态库方法。

Windows DLL未链接。 因此,您无法跨DLL共享静态对象。 它就像你的地址空间中的一个单独的程序。

Unix共享对象在运行时实际上是“链接”的,就像同一个项目的不同模块一样,执行符号解析。

动态链接和库加载都在运行时发生,但动态链接在程序执行之前完成,由系统链接器完成。 因此,例如,如果缺少必需的库,则无法执行程序。 另一方面,库加载是由程序本身通过dlopen / LoadLibrary函数完成的。 在这种情况下,加载过程由应用程序控制,应用程序可以例如处理错误。