前言
我们知道编译器会将程序源文件编译成一个个独立的模块,然后在按照需要组装起来,这个组装的过程就是链接,链接又分为静态和动态链接,
库是一个个目标文件的集合,因此静态库一般都是指的由静态链接的目标文件集合,而动态库一般是动态链接目标生成的目标集合,那么静态链接和动态链接到底是什么
静态链接
过程
- 空间与地址分配
扫描所有输入目标文件,获得各个段的长度,属性和位置,并且将输入目标文件中的符号表中的所有符号定义和符号引用收集,统一放到一个全局符号表,获得所有输入目标文件的段长度,将他们合并,计算出输出文件的各个段合并后的长度与位置,并建立映射关系。 - 符号解析与重定位
读取上一步收集到的信息,读取输入文件的段数据,重定位信息,进行符号解析和重定位,调整代码中的地址。
生成方法
静态库
gcc -c source1.c source2.c …
ar -rs xxx.a source1.o source2.o …
可执行程序
gcc -static source1.c source2.c xxx.a
动态链接
过程
启动动态链接器本身=>装载共享对象=>重定位以及初始化=>链接完成,将进程控制权转交程序入口并开始执行。
生成方法
动态库
可执行程序
gcc 默认链接方式就是动态态链接
gcc source1.c source2.c …-lXXX //库名为libxxx.so
区别
区别 | 静态链接 | 动态链接 |
---|---|---|
链接时机 | 程序装载前 | 装载时或者运行时 |
空间占用 | 大 | 小 |
程序执行速度 | 快 | 稍慢5%左右 |
谁来链接 | ld | 动态链接器(linux 下为/lib/ld-xxx.so) |
库文件后缀 | .a | .so |
内存分析
- 先用静态链接编译运行程序file,查看内存分布情况:如下
- 再用动态链接编译运行程序file,查看内存分布情况:
3.重新编译个使用同一共享库的动态可执行程序,查看内存分布
备注: 26153(静态) ,26163 (动态)的程序代码一摸一样,只是链接方式不一样,而26849和26163 共享libc 库
总结分析来看
1:不同链接方式的地址空间分配不一样,动态链接库和可执行代码的代码段和数据段的地址均分开分配
2.不同进程下,同一个动态库需要重新加载。所以动态库的共享只是源文件的共享,节省了主存空间,运行时,不同进程之间,共享库并不共享,是独立的,