Linux共享库

共享库

从文件结构上讲,共享库和共享对象没什么区别,Linux下共享库就是普通的ELF共享对象。由于共享对象可以被各个程序之间共享,所以它也就成为了库的很好的存在形式,很多库的开发者都以共享对象的形式让程序来使用。

共享库的版本

共享库的兼容

我们知道,共享库是在不断更新的。但是这种更新也会导致接口的更改和删除。这个时候,就可能导致依赖共享库的程序无法正常运行。

一般来说,共享库的更新是有两种的:

  • 兼容更新。所有的更新只是在原有的共享库基础上添加一些内容。
  • 不兼容更新。更新会改变原有的接口。

注意!我在这里写到的接口是指ABI而不是API。

导致ABI改变的行为

一般改变C语言的ABI有四种主要的行为:

  1. 导出函数的行为发生改变。也就是说调用这个函数以后产生的结果和以前的不一样,对函数的执行逻辑进行了改变
  2. 导出函数被删除
  3. 导出数据的结构发生变化,比如共享库定义的结构体变量的结构发生改变,即对导出函数的返回值,参数列表的删除或者名称的修改。
  4. 导出函数的接口发生变化。如函数返回值、参数被更改。

当然还有其他行为:
比如说不通版本的编译器、操作系统和硬件平台等。

如何保持ABI兼容

对于C++,ABI问题会更加的严重,因为有虚函数表,模板实例化,多重继承等问题。

但是,一般来说,按照以下的规则编写C++共享库基本就可以保持ABI兼容。

  • 不要在接口中使用虚函数,万不得已要使用虚函数时,不要随意删除、添加或在子类中添加新的实现函数。
  • 不要改变类中任何成员变量的位置和类型。
  • 不要删除非内嵌的public或protected成员函数。
  • 不要将非内嵌的成员函数改成内嵌成员函数。
  • 不要改变成员函数的访问权限。
  • 不要在接口中使用模板
  • 不要改变接口的任何部分干脆不要使用C++作为共享库接口。

共享库版本命名

Linux规定共享库的文件名规则必须如下:

libname.so.x.y.z

后面跟的三个数字组成了版本号。
“x”表示主版本号

主版本号表示库的重大升级,不同主版本号的库之间是不兼容的

“y”表示次版本号

次版本号表示库的增量升级,即增加了一些新的符号接口,且保持原来的符号不变。在主版本号相同的情况下,高的次版本号向后兼容低的次版本号的库。

“z”表示发布版本号

发布版本号表示库的一些错误的修正、性能的改进等,并不添加任何新的接口,也不对某个接口进行更改。相同主版本号、次版本号的共享库,不同发布版本号之间完全兼容

程序如何获取依赖共享库信息

我们假定程序中有一个它所依赖的共享库列表,其中每一项对于于它所依赖的一个共享库。

SO-NAME

对于Linux来说,普遍会采用一个叫SO-NAME的命名机制来记录共享库的依赖关系。每个共享库都有一个对应的SO-NAME

SO-NAME即共享库的文件名只保留主版本号。

如 libfoo.so.2.1.6 的SO-NAME就是 libfoo.so.2

显然,我们可以得出SO-NAME相同的两个共享库,次版本号大的兼容次版本号小的。

SO-NAME的优势

SO-NAME其实是一个软链接。实际上这个软链接会指向目录中主版本号相同、次版本号和发布版本号最新的共享库。

所以它的优势在于:
不用更改程序,直接更改软链接

总之,SO-NAME表示一个库的接口,接口不想后兼容,SO-NAME就会发生变化。

链接名

当我们在编译器使用共享库的时候,我们会使用更简洁的方式。

比如需要链接一个libXXX.so.2.6.1,就只需要在shell脚本中输入-lXXX就行

共享库的系统路径

FHS规定,一个系统中主要有两个存放共享库的位置:

  • /lib ,这个位置主要存放系统最关键和基础的共享库
  • /usr/lib 这个目录下主要保存的是一些非系统运行时所需要的关键性的共享库
  • /usr/local/lib,这个目录用来存放一些跟操作系统本身并不十分相关的库。

FHS,一个大多数开源操作系统都遵循的标准

共享库的查找过程

在linux中,动态链接的ELF可执行文件在启动时会同时启动动态链接器/lib/ld-linux.so.X,程序所依赖的共享对象全部由动态链接器负责装载初始化

任何一个动态链接的模块所依赖的模块路径保存在dynamic段中,由DT_NEED类型的项表示。动态链接器对于模块的查找有一定的规则:

如果DT-NEED里面保存的是绝对路径,那么动态链接器就会按照这个路径去查找。如果是相对路径,那么动态链接器就会在/lib/usr/lib和由/etc/ld.so.conf配置文件指定的目录中查找共享库。

但是!

每次都去找这个目录是否是太过笨逼?

所以Linux中引入了一个叫ldconfig的小程序,它会把共享库目录下的各个共享库创建、删除或更新相应的SO-NAME,这样每个共享库的SO-NAME就能够指向正确的文件共享库;并且这个程序还会将这些SO-NAME收集起来,集中存放到/etc/ld.so.cache文件,并建立一个SO-NAME的缓存

参考文献

 [1] 俞甲子 石凡 潘爱明.程序员的自我修养.电子工业出版社,2009.4.
全部评论

相关推荐

10-05 11:11
海南大学 Java
投票
理想江南137:感觉挺真诚的 感觉可以试一试
点赞 评论 收藏
分享
评论
点赞
收藏
分享
正在热议
# 25届秋招总结 #
440737次浏览 4493人参与
# 春招别灰心,我们一人来一句鼓励 #
41503次浏览 524人参与
# 北方华创开奖 #
107320次浏览 599人参与
# 地方国企笔面经互助 #
7930次浏览 18人参与
# 同bg的你秋招战况如何? #
75684次浏览 552人参与
# 虾皮求职进展汇总 #
114355次浏览 884人参与
# 阿里云管培生offer #
119909次浏览 2219人参与
# 实习,投递多份简历没人回复怎么办 #
2454094次浏览 34848人参与
# 实习必须要去大厂吗? #
55687次浏览 960人参与
# 提前批简历挂麻了怎么办 #
149836次浏览 1977人参与
# 投递实习岗位前的准备 #
1195731次浏览 18546人参与
# 你投递的公司有几家约面了? #
33181次浏览 188人参与
# 双非本科求职如何逆袭 #
661934次浏览 7394人参与
# 如果公司给你放一天假,你会怎么度过? #
4734次浏览 55人参与
# 机械人春招想让哪家公司来捞你? #
157604次浏览 2267人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11381次浏览 271人参与
# 发工资后,你做的第一件事是什么 #
12431次浏览 61人参与
# 工作中,努力重要还是选择重要? #
35621次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20091次浏览 240人参与
# 我的上岸简历长这样 #
451933次浏览 8088人参与
# 实习想申请秋招offer,能不能argue薪资 #
39241次浏览 314人参与
# 非技术岗是怎么找实习的 #
155852次浏览 2120人参与
牛客网
牛客企业服务