DLL hell 是指 Windows 系统上动态库的新版本覆盖旧版本,且新版本不能兼容旧版本的问题。
例如:装新软件,但原有的软件运行不起来了。
 
Linux 系统下也同样面临着和 Windows 一样的动态库多版本的问题,其严重影响软件的升级和维护。

那么此问题该如何解决的呢?
Linux 系统为解决这个问题,引入了一套机制,如果遵守这个机制来做,就可以避免这个问题。
但是这只事一个约定,不是强制的。
但是建议遵守这个约定,否则同样也会出现 Linux 系统版的 DLL hell 问题。

下面来介绍一个这个机制。
这个机制是通过文件名,来控制共享库(Shared Library)的版本,它有三个名字,分别又有不同的目的。

1)第一个是共享库的实际文件名(Real Name),
  它是编译器产生共享库时或人为修改名字后的文件名,该实际文件名就是为了直观地控制共享库版本。
  其格式为:lib + math + .so + 主版本号 + 小版本号 + 制作号
  如:libmath.so.1.1.1234。
 
  lib      是 Linux 系统上的库的约定前缀名,
  math     是库自已的名字,
  so       是共享库的后缀名,
  1.1.1234 是共享库的版本号,
           格式:主版本号 + 小版本号 + 制作(build)号。
              主版本号 - 代表当前共享库的版本,
                     如果共享库提供的接口函数有变化的话,那么这个版本号就要加壹(1);
              小版本号 - 如果引入了新的特性(Feature)的话,那么这个版本号就要加壹(1);
              制作号  - 一般仅表示修正了Bug。

2)第二个是共享库的简短文件名(soname - Short for shared object name),
  它是可执行程序加载它时,要寻找的文件名。
  其格式为:lib + math + .so + 主版本号
  如:libmath.so.1
  注:在编译链接生成一个实际文件名的共享库时,同时也将简短文件名写进了共享库的文件头里面。
    可以用此命令来查看:$readelf -d 共享库的实际文件名

3)第三个是共享库的连接文件名(Link Name),
  是专门为可执行程序生成阶段链接共享库时用的名字,不带任何版本信息的。
  其格式为:lib + math + .so
  如:libmath.so。

 
 
 
在可执行程序链接共享库时:首先会用到共享库的连接文件名,通过连接文件名找到共享库; 然后会取出共享库的简短文件名,并写在共享库自己的文件头里面。
在可执行程序加载共享库时: 通过共享库的简短文件名在给定的路径下寻找共享库。
 
举例说明:
一 源代码
//hello.h
void hello(); 
 
//hello.c
#include "hello.h" 
 #include <stdio.h>
 void hello() {
     printf("libhello");
 }
 
//main.c
#include "hello.h"
int main() {
     hello(); 
}
 
二 生成
1.生成动态链接库
# gcc hello.c -shared -fPIC -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0
 
2.运行readelf -d libhello.so.0.0.0显示:
[qingze@localhost tst]$ readelf -d libhello.so.0.0.0 
Dynamic section at offset 0xe08 contains 25 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libhello.so.0]
0x000000000000000c (INIT) 0x588
0x000000000000000d (FINI) 0x708
0x0000000000000019 (INIT_ARRAY) 0x200de8
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x200df0
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x380
0x0000000000000006 (SYMTAB) 0x230
0x000000000000000a (STRSZ) 190 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x201000
0x0000000000000002 (PLTRELSZ) 72 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x540
0x0000000000000007 (RELA) 0x480
0x0000000000000008 (RELASZ) 192 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x460
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x43e
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0
 
3. 执行ldconfig -vn .  (有点),在当前目录县生成soname链接到 libhello.so.0.0.0,此时如下:
运行前:
[qingze@localhost tst]$ ll
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
运行后:
[qingze@localhost tst]$ ll
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
 
4.运行 ln -s libhello.so.0 libhello.so:
[qingze@localhost tst]$ ll
total 20
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 13 Nov 29 15:33 libhello.so -> libhello.so.0
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
 
5.运行gcc main.c -o main -Wl,-rpath=./ -L. -lhello
[qingze@localhost tst]$ ll
total 32
-rw-rw-r--. 1 qingze qingze 79 Nov 29 13:47 hello.c
-rw-rw-r--. 1 qingze qingze 14 Nov 29 12:44 hello.h
lrwxrwxrwx. 1 qingze qingze 13 Nov 29 15:33 libhello.so -> libhello.so.0
lrwxrwxrwx. 1 qingze qingze 17 Nov 29 15:30 libhello.so.0 -> libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8005 Nov 29 15:19 libhello.so.0.0.0
-rwxrwxr-x. 1 qingze qingze 8538 Nov 29 15:36 main
-rwxrwxr-x. 1 qingze qingze 48 Nov 29 15:26 main.c
 

gcc编译链接动态库时,很有可能编译通过,但是执行时,找不到动态链接库,那是

因为-L选项指定的路径只在编译时有效,编译出来的可执行文件不知道-L选项后面的值,

当然找不到。可以用ldd <your_execute>看看是不有 ‘not found’在你链接的库后面,

解决方法是通过-Wl,rpath=<your_lib_dir>,使得execute记住链接库的位置

个人理解:

参考了网上一些资料,一步步执行时会发生错误,我按照以上方法成功了,所以我认为当动态链接库版本发生变化时只要重新执行第4步,将libhello.so链接到新版本即可!

有待求证!!!

linux dll hell--链接库real name, soname, link name的更多相关文章

  1. linux c静态链接库与动态链接库

    库函数是我们编程的时候经常用到的,我们协作编程的时候可以将常用的函数封装成库供大家使用,这样能够提高大家的工作效率.对于库函数,它分为动态链接库和静态链接库.对于静态链接库我们必须是连接到可执行文件中 ...

  2. linux下静态链接库的用法

    最近在Linux下编程发现一个诡异的现象,就是在链接一个静态库的时候总是报错,类似下面这样的错误: (.text+0x13): undefined reference to `func' 关于unde ...

  3. Linux编程中链接库的使用

    链接库本质上是一段可执行的二进制代码,可以被操作系统载入内存执行.按加载的时机不同,链接库可以分为静态链接库和动态链接库. 静态链接库:编译过程中加载进可执行文件的库(静态库省去了运行时加载的消耗,但 ...

  4. Linux下 静态链接库 和 动态链接库

    先来说说C/C++编译过程 编译: 检查语句符号定义,将C/C++代码翻译生成中间语言. 链接: 将中间代码整合,生成可执行的二进制代码. 简单的说,库文件都是一种特殊的中间语言文件,静态库还是一种特 ...

  5. linux下静态链接库和动态链接库

    关于链接库的知识,网上太多资料了,但是并不代表我很熟悉.今天遇到了 一个问题,就是由于静态链接库和ubuntu系统不兼容导致的,虽然花了点时间才搞定 但是,其中暴露的问题也不少. 没有区分好静态链接库 ...

  6. linux动态链接库和静态链接库

    Linux下静态链接库与动态链接库的区别 引言 通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件 (object file)与牵涉到的函数库(librar ...

  7. 创建和使用Windows静态链接库

    首先明确这篇文章的目的,我希望大家能够通过这篇文章了解一下如何在实际工作中创建和使用Windows平台下的静态链接库.关于链接库的概念,希望大家参考维基百科"Library"词条( ...

  8. linux下动态链接库.so文件 静态链接库.a文件创建及使用

    转摘网址为:http://www.cnblogs.com/fengyv/archive/2012/08/10/2631313.html Linux下文件的类型是不依赖于其后缀名的,但一般来讲:    ...

  9. 动态链接库dll,导入库lib,静态链接库lib

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库” ...

随机推荐

  1. Node.js学习疑惑整理

    1.Node.js 在调用某个包时,会首先检查包中 package.json 文件的 main 字段,将其作为 包的接口模块,如果 package.json 或 main 字段不存在,会尝试寻找 in ...

  2. jquery.uploadify上传图片,点击保存按钮无法使用解决方法

    用Chrome浏览器上传商品图片时,保存按钮无法点击,如下图 原因:Flash插件状态为禁止 或 询问(默认) 解决方法:将Flash插件状态改为允许,如下图

  3. python去噪算法

    <programming computer vision with python >中denoise 算法有误,从网上好了可用的代码贴上,以便以后使用. 书中错误的代码: def deno ...

  4. Win7使用初体验

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近装了个Win7旗舰版.随着年纪渐大,我对软件使用越来越趋于务实,不再追求最新版本,因为我评价一个好软件的标准是适用 ...

  5. WPF 的毛玻璃效果

    原文:WPF 的毛玻璃效果 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/koloumi/article/details/76917519 其实很简 ...

  6. WPF 窗体基类实现的体验及实现回车到下一控件

    原文:WPF 窗体基类实现的体验及实现回车到下一控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/jsyhello/article/details ...

  7. js 将json字符串转换为json对象

    要引入:jquery-json-2.4.js 在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键.例如: JS ...

  8. WPF自定义LED风格数字显示控件

    原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/de ...

  9. 微信小程序之商品属性分类

    所提及的购物数量的加减,现在说说商品属性值联动选择. 为了让同学们有个直观的了解,到电商网截了一个图片,就是红圈所示的部分 现在就为大家介绍这个小组件,在小程序中,该如何去写 下图为本项目的图: wx ...

  10. 【Android发展】它Fragment发展1

    一直知道Fragment非常强大.可是一直都没有去学习,如今有些空暇的时间,所以就去学习了一下Fragment的简单入门.我也会把自己的学习过程写下来,假设有什么不足的地方希望大牛指正,共同进步. 一 ...