说道“动态库版本兼容”,很多人头脑中首先蹦出的就是“Dll Hell”。啊,这曾经让人头疼的难题。时至今日,这个难题已经很好地解决了。
 
在进一步讨论之前来思考一个问题:Linux下为什么没有让人头痛的“DllHell”?
回答这个问题,非常easy,因为——Linux下根本没有dll!
 
哈哈,当然这只是个玩笑,接下来展开一下这个话题,很多有动态库的系统都会面临这个难题,但各自解决的思路却各不相同。
 
Dll hell是指windows 上动态库新版本覆盖旧版本,但是却不兼容老版本。常常发生在程序升级之后,动态库更新,原有程序运行不起来;或者装新软件,但是已有的软件运行不起来。
 
一、linux下的解决方案——命名规范
Linux 上的Dll ,叫sharedlibrary。Linux 系统面临和Window一样的问题,如何控制动态库的多个版本问题。为解决这个问题,Linux 为解决这个问题,引入了一套命名机制,如果遵守这个机制来做,就可以避免这个问题。但是这只事一个约定,不是强制的。但是建议遵守这个约定,否则同样也会出现 Linux 版的Dll hell 问题。
 
Real Name
首先是共享库本身的文件名:共享库的命名必须如 libname.so.x.y.z
最前面使用前缀”lib”,中间是库的名字和后缀”.so”,最后三个数字是版本号。x是主版本号(Major Version Number),y是次版本号(Minor Version Number),z是发布版本号(Release Version Number)。
 
主版本号(不兼容):重大升级,不同主版本的库之间的库是不兼容的。所以如果要保证向后兼容就不能删除旧的动态库的版本。
 
次版本号(向下兼容): 增量升级,增加一些新的接口但保留原有接口。高次版本号的库向后兼容低次版本号的库。
 
发布版本号(相互兼容):库的一些诸如错误修改、性能改进等,不添加新接口,也不更改接口。主版本号和此版本号相同的前提下,不同发布版本之间完全兼容。
 
SO-NAME
严格遵守上述规定,确实能避免动态库因为版本冲突的问题,但是读者可能有疑问:在程序加载或运行的时候,动态链接器是如何知道程序依赖哪些库,如何选择库的不同版本?
Solaris和Linux等采用SO-NAME( Shortfor shared object name )的命名机制来记录共享库的依赖关系。每个共享库都有一个对应的“SO-NAME”(共享库文件名去掉次版本号和发布版本号)。比如一个共享库名为libtest.so.3.8.2,那么它的SO-NAME就是libtest.so.3。
 
 
在Linux系统中,系统会为每个共享库所在的目录创建一个跟SO-NAME相同的并且指向它的软连接(Symbol Link)。这个软连接会指向目录中主版本号相同、次版本号和发布版本号最新的共享库。也就是说,比如目录中有两个共享库版本分别为:/lib/libtest.so.3.8.2和/lib/libtest.so.3.7.5,么软连接/lib/libtest.so.3指向/lib/libtest.so.3.8.2。
 
建立以SO-NAME为名字的软连接的目的是,使得所有依赖某个共享库的模块,在编译、链接和运行时,都使用共享库的SO-NAME,而不需要使用详细版本号。在编译生产ELF文件时候,如果文件A依赖于文件B,那么A的链接文件中的”.dynamic”段中会有DT_NEED类型的字段,字段的值就是B的SO-NAME。这样当动态链接器进行共享库依赖文件查找时,就会依据系统中各种共享库目录中的SO-NAME软连接自动定向到最新兼容版本的共享库。
 
★  readelf -d sharelibrary 可以查看so-name
★  Linux提供了一个工具——ldconfig,当系统中安装或更新一个共享库时,需要运行这个工具,它会遍历默认所有共享库目录,比如/lib, /usr/lib等,然后更新所有的软链接,使她们指向最新共享库。
 
Link Name
 
当我们在编译器里使用共享库的时候,如用GCC的“-l”参数链接共享库libtXXX.so.3.8.1,只需要在编译器命令行指定 -l XXX 即可,省略了前缀和版本信息。编译器会根据当前环境,在系统中的相关路径(往往由-L参数指定)查找最新版本的XXX库。这个XXX就是共享库的“链接名”。不同类型的库可能有相同的链接名,比如C语言运行库有静态版本(libc.a)也动态版本(libc.so.x.y.z)的区别,如果在链接时使用参数”-lc”,那么连接器就会根据输出文件的情况(动态/静态)来选择合适版本的库。eg. ld使用“-static”参数时吗,”-lc”会查找libc.a;如果使用“-Bdynamic”(默认),会查找最新版本的libc.so.x.y.z。
 
更详细可以参见
http://www.linuxidc.com/Linux/2012-04/59071.htm
 
 
.Net下的解决方案——Manifest文件
.Net框架中,一个程序集(Assembly)有两种类型:应用程序程序集(.exe)与库程序集(DLL动态链接库)。一个程序集包括一个或个文件,所以需要一个清单文件(Manifest文件)来描述程序集。Manifest文件描述了程序集的名字,版本号以及程序集的各种资源,同时也描述了该程序集的运行所依赖的资源,包括DLL以及其他资源文件等。Manifest是一个XML文件。每个DLL有自己的Manifest。对于应用程序而言,manifest文件可以和可执行文件在同一目录,也可以作为一个资源嵌入到可执行文件内部(Embed Manifest)。
 
XP以前的windows版本,在执行可执行文件是不会考虑manifest文件的。它会直接到system32目录下查找可执行文件锁依赖的DLL。在这种情况下,manifest是多余的。XP之后的操作系统,在执行可执行文件时则会首先读取程序集的manifest文件,获得该可执行文件需要调用的DLL列表,操作系统再根据DLL的manifest文件去寻找对应的DLL调用。
 
 
Windows的解决方案——COM组件
采用标准COM组件,有很多好处:面向接口和对象编程语言无关性,采用二进制标准,可以实现跨语言调用版本升级方便,增加新接口,组件升级后老客户程序不用重新编译位置透明,客户程序不用关心组件的位置重用方便,通过包容和聚合可以快速重用已有组件我们可以看到标准COM组件非常强大,但是很多时候我们并不需要标准COM组件的所有特性,比如我们不希望引入注册表,也不希望引入COM运行库,我们希望我们的程序是完全“绿色”的。这时我们就会采用“COM思想架构“开发非标准的COM组件。

linux动态库命名规则相关推荐

  1. Linux动态库和静态库比较

     Linux动态库和静态库比较文件预览 文件目录树如下,如你所见,非常简单.    1. libtest/    2. |-- lt.c    3. |-- lt.h    4. `-- test.c ...

  2. 分析Windows和Linux动态库

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  3. Windows和Linux动态库比较 (Zhuan)

    Windows和Linux动态库比较 Description: 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库 可以有效的减少程序大小,节 ...

  4. bazel 链接第三方动态库_C/C++编程知识:Linux 动态库相关知识整理

    动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序,动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执行程序等诸多好处.作者是一个Linux后台开发,这些知 ...

  5. linux代码动态分析软件,举例分析Linux动态库和静态库

    函数库分为静态库和动态库两种.创建Linux静态库和Linux动态库和使用它们在这里将以举例的形式详述一下.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不 ...

  6. linux动态链接库的使用,Linux动态库soname的使用

    通过一个简单的例子,体验一下Linux动态库soname的使用. 假设有一个动态库:libbar.so.1.1.0,其对应的三个名称如下. realname:libbar.so.1.1.0 sonam ...

  7. 举例分析Linux动态库和静态库

    转自:http://www.xxlinux.com/newxxlinux/development/gui/2012-01-05/499.html 函数库分为静态库和动态库两种.创建Linux静态库和L ...

  8. Linux动态库(.so)搜索路径

    众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib.动态库被创建后,一般都复制到这两个目录中.当程序执行时需要某动态库,并且该动 态库还未加载到内存中,则系统会自动到这两个默认搜索路 ...

  9. 阐述Linux动态库的显式调用

    阐述Linux动态库的显式调用 分类: Linux 2011-02-12 10:27 168人阅读 评论(0) 收藏 举报 linux测试nulllibrarypathgcc 十年的发展,Linux系 ...

最新文章

  1. IB网络用户数量超过私有网络近4倍
  2. 小知识六、CALayer动画
  3. Codeforces Round #703 (Div. 2) B.Eastern Exhibition 中位数结论
  4. TortoiseGit 冲突和解决方案_入门试炼_07
  5. leetcode - 764. 最大加号标志
  6. C语言课后习题(10)
  7. Git学习总结(3)——代码托管平台简介
  8. face 3000 C++ 代码理解
  9. 基于评论文本的深度推荐系统总结
  10. 数据挖掘之CTR预估(FM算法)
  11. JavaScript对象Object
  12. 利用后中遍历结果,重构二叉树
  13. php laypage 开发demo,laypage+laytpl示例
  14. 历时两年,秘鲁四人调查团队发布反腐 AI
  15. 详解Guitar Pro 7小节的组织定义
  16. Java实现图片批量压缩像素
  17. 用74ls90组成二十四进制计数器_减法计数器的组成以及原理
  18. 计算机行业各种职业技能树
  19. JS逆向之巨量算数signature与data解密
  20. css inherit

热门文章

  1. 鸿蒙os操作系统合作伙伴,华为公布三大鸿蒙OS系统 已有大量合作伙伴进行开发...
  2. java把图片写入excel_使用POI向excel中写入图片的java代码
  3. C语言面试题-这些简单的你能很快的写出来吗?
  4. 5行Python提取海量新闻网站内容
  5. R6010-abort() has been called,Error openning file ../../modules/highgui/src/cap_ffmpeg_impl.hpp解决方法
  6. 【OpenCV】将单通道的Mat对象转换为三通道的Mat
  7. Intro to Parallel Programming CUDA-第二单元
  8. 【亲测可用→防止入坑Routes】设置angular10项目异步加载、惰性加载、懒加载路由
  9. vue 编写H5页面在公众号外部获取手机本地坐标经纬度
  10. 进一步封装axios并调用其读取数据(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)