【计算机基础】静态链接与动态链接

导读:本篇文章讲解 【计算机基础】静态链接与动态链接,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com


一、前言

一段代码从文本编辑器上产生到最终能够在机器上运行,经历了非常多的阶段,概括而言,至少包含了以下几个阶段:

  1. 编译 : 编译器通过词法分析,语法分析,语义分析等,将一段代码翻译成汇编语言;再将汇编语言翻译成机器指令,生成可重定位的二进制目标文件。
  2. 链接 :解决符号之间的重定位问题。
  3. 装载 :将可执行文件加载到内存。

以下内容详细介绍编译与链接过程。


二、编译

编译完成的是从源文件到二进制文件的转换过程。

编译分为三步:

  1. 对源文件进行预处理:处理一些 # 号定义的命令或语句(如宏、#include、预编译指令 #ifdef等),生成*.i文件;
  2. 编译:词法分析、语法分析和语义分析等,生成*.s的汇编文件;
  3. 汇编:将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。

以上就是编译的过程。

编译结束之后,需要进行链接。


三、链接

链接分为 静态链接动态链接 两种方式。

1. 静态链接

静态链接就是在 装载之前,就完成所有的符号引用的一种链接方式。

在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。目标文件中有两个重要的接口来提供这些信息:一个是符号表,另外一个是重定位表。

静态链接的处理过程分为2个步骤:

  1. 空间与地址的分配。扫描所有的目标文件,合并相似段,收集当中所有的符号信息。
  2. 符号解析与重定位。调整代码位置。

优点:在程序发布的时候就不需要依赖库,也就是不再需要带着库一块发布,程序可以独立执行。

缺点

  1. 浪费内存空间。在多进程的操作系统下,同一时间,内存中可能存在多个相同的公共库函数。
  2. 程序的开发与发布流程受模块制约。 只要有一个模块更新,那么就需要重新编译打包整个代码。

为了解决以上2个问题,就诞生了动态链接。

2. 动态链接

基本思想就是将对符号的重定位推迟到程序 运行时 才进行。

在编译的时候不直接拷贝可执行代码,而是通过 记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。

只要推迟到运行时进行符号的重定位,就能解决静态链接的两个缺点:

  1. 对于第一个缺点:在运行时重定位,如果在运行过程中调用了公共库函数或者其他模块的函数,系统只需要在内存中维护一份公共库代码即可,只要将不同应用程序对公共库函数的调用地址设置成相同即可。多个程序可以共享同一段代码,而不需要在磁盘上存储多个拷贝。
  2. 对于第二个缺点:理论上只要将需要替换的模块更新,无需将整个应用程序打包。

优点: 解决了静态链接的缺陷,更适应现代的大规模的软件开发。

缺点

  1. 结构复杂。

    对于静态链接来说,系统只需要加载一个文件(可执行文件)到内存即可,但是在动态链接下,系统需要映射一个主程序和多个动态链接模块,因此,相比于静态链接,动态链接使得内存的空间分布更加复杂。

    不同模块在内存中的装载位置一定要保证不一样。

  2. 由于是运行时加载,可能会影响程序的前期执行性能。

  3. 引入了安全问题,这也是我们能够进行PLT HOOK的基础。

3. 总结

静态链接库的优点:

  1. 代码装载速度快,执行速度略比动态链接库快;

  2. 只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。

动态链接库的优点:

  1. 更加节省内存并减少页面交换;

  2. DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性;

  3. 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数;

  4. 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。


四、库

上述多次提到库(lib)这个概念,所谓库就是一些功能代码经过编译连接后的可执行形式。

库也有静态lib和动态lib之分:

  1. 静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序。
  2. 动态lib相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持。

参考链接

  1. 深入浅出静态链接和动态链接
  2. 动态链接与静态链接
  3. 静态链接与动态链接的区别

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118921.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!