Q:静态库和共享库的区别
A:
静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率
linux上扩展名不同: 静态库以.a结尾,共享库以.so结尾
linux储存位置:静态库的保存位置和共享库是一样的 /lib(系统启动时需要的库,执行shell需要的库,是系统最关键的库) /usr/lib(开发时用到的库)
加载时间不同:静态库在静态链接时使用,每个程序都有一份 共享库在动态链接时使用
所以使用静态库的缺点是:在多进程操作系统下
- 浪费内存和磁盘空间
- 修改静态库后,需要重新链接
共享库就是为了解决静态库的这些缺点:节省内存,减少物理页面的换入换出,增加cpu的缓存命中率
生成静态库和共享库的命令:
ar:
选项前可以有‘-‘字符,也可以没有
r:在库中插入模块(替换)。
c:创建一个库。不管库是否存在,都将创建。
v:该选项用来显示执行操作选项的附加信息
静态库:
首先将源文件编译成目标文件:gcc –c a.c b.c
生成静态库:ar crv libstatic.a a.o b.o
共享库:
同静态库一样编译成目标文件:gcc –c a.c b.c
生成共享库:gcc –fPIC –shared –o libshared.so a.o b.o
-shared 产生共享对象
-fPIC 使用地址无关技术(如果没有这命令选项,产生的将是装载时重定位对象)
/proc/pid/maps
内存段虚拟地址 执行权限 进程地址里偏移量 映射文件的主设备号和次设备号(cat /proc/devices) 映像文件路径
readeld –l Lib.so
判断一个DSO是否为PIC的办法
readelf –d foo.so | greap TEXTREL(重定位表地址)
有信息就表示有重定位表,那么就不是PIC
库文件:一组编译好的函数集合
ld-2.6.so 动态链接器
linux命名共享库的规则:
libname.so.x.y.z
前缀"lib"+ 自定义名字"name"+ 后缀"so"
x:主版本号 y:次版本号 z:发布版本号
glibc不遵守规则,使用 libc-x.y.z.so
ldconfig更新共享库
静态库使用静态链接
共享库使用动态链接
动态链接:
就是把链接的过程推迟到了运行的时候
在链接的时候,共享库也作为链接的输入文件之一,
符号解析的时候,把源文件中
重定位推迟到运行程序的时候
装载时重定位程序运行时,共享库模块地址确定,系统对程序中所有的绝对地址进行重定位
优化动态链接性能:
地址无关代码:把指令中需要修改的部分分离出来,和数据部分放一起,内存就不会有多份指令的拷贝了,因为指令都一样
延迟绑定:当函数第一次被用到才进行绑定