深入理解计算机系统_静态链接和动态链接以及静态库和动态库

这篇文章记录静态链接和动态链接以及静态库和动态库的原理。

1 静态链接和动态链接

链接其实就是连接的意思,将所有相关的东西连接起来。

1.1 静态链接

什么是静态链接?编译时候的链接就是静态链接,所以ld/collect2链接程序,也称为静态链接器。在编译时候,调用gcc自动调用ld/collect2链接程序,将所有的.o文件整合在一起,然后保存在可执行文件中。
静态链接做了两件事情,分别是符号解析和重定位。

1.1.1 符号解析

符号解析的目的就是将每个X.c生成的目标文件X.o中的引用和符号的定义联系起来。
在这里插入图片描述

1.1.2 重定位

重定位做的事情:将.o文件中每个机器指令的逻辑地址,重定位为实际运行的地址(虚拟内存地址)。如果是裸机运行的:运行的地址就是内存的物理地址;如果是基于OS运行的:运行地址就是虚拟内存的地址。不过虚拟内存机制,最终还是会将虚拟地址会转为物理地址。
在这里插入图片描述
上图中,每个段开始都是逻辑地址,从0开始的一个编号,这个编号只是一个编号,既不是虚拟内存地址也不是物理地址,就是一个标识。
通过collect2链接后,就可以将这些段的编号重定位成虚拟内存地址,如下图所示:
在这里插入图片描述

1.2 动态链接

动态链接,就是在编译时候只留下调用接口(函数所在库的相对地址),当程序真正运行时候,才去链接执行。动态链接不是在编译时发生的,而是在程序动态运行时发生的,所以叫称为动态链接。比如,printf,这个函数就是动态库提供的,程序编译后在调用printf处,只留下动态库的printf接口,程序运行起来后再去调用Printf函数。
下面说一下,什么是静态库和动态库?

2 静态库和动态库

这两个文件都是由许多.o文件打包成的文件,相当于一个文件仓库。

2.1 静态库

链接静态库时,就是将库中.o的代码包含到自己的程序中,每个程序链接静态库后,都会包含一份独立的代码,当这些程序都运行起来时,所有这些重复的代码都需要占独立的存储空间,显然很浪费计算机资源。

2.2 动态库

动态库就是为了解决静态库的缺点。
在链接动态库时,collect2/ld不会将动态库中.o的代码直接静态链接(复制)到自己程序中,只会留下调用接口。程序运行时再去将动态库(链接)加载到内存中,然后就能调用动态库的函数(代码)了。不管多少程序使用了这个动态库,这些程序只会共享使用同一份的动态库(只加载一份在内存中),因此动态库也被称为共享库。

动态库的实现原理

程序运行起来后,“动态链接器”一看想链接的是libc.so动态库,首先检查内存中有没有这个动态库。如果没有:到硬盘上找到libc.so库,将所有代码加载(动态链接)到内存中,并得到整个动态库在内存中的起始地址;如果有,说明之前已经加载过了,所以不再加载,直接得到动态库在内存中的起始地址即可。
我们调用动态库的printf时候,如何找到这个函数?
Printf编译后,程序中留下printf 在动态库中的相对地址。
在这里插入图片描述
Printf的绝对地址= printf的相对地址 + 动态库加载时候的地址
在这里插入图片描述
当动态链接器加载动态库之后,会得到动态库在内存中的起始地址,通过上边的计算公式,就得到了printf的真正地址。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值