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. DapperPoco

    DapperPoco -- 基于Dapper的.轻量级的.高性能的.简单的.灵活的ORM框架 为什么要重复造轮子 因为现有的轮子都在某些方面不太令我满意,下面我来一一点评一下,欢迎拍砖. Entity ...

  2. javascript学习-创建json对象数据,遍历

    之前我已经有讲过后台返回json数据到前台,并在前台遍历json数据. 这里讲下直接在JS里创建JSON数据,然后遍历使用~ 创建代码例如以下:(创建的是JSON对象) var YearSelect ...

  3. idhttp post 出现exception class EIdSocketError with message 'Socket Error # 10054的解决办法(捕捉异常,防止程序挂掉)

    由于项目需要.需要向一个地址提交数据.提交的次数很频繁,但是程序经常raised exception class EIdSocketError with message 'Socket Error # ...

  4. Attribute-based identification schemes for objects in internet of things

    Methods and arrangements for object identification. An identification request is received from diffe ...

  5. Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来

    首先题外话,今天早上起床的时候,手滑一下把我的手机甩了出去,结果陪伴我两年半的摩托罗拉里程碑一代就这么安息了,于是我今天决定怒更一记,纪念我死去的爱机. 如果你是网购达人,你的手机上一定少不了淘宝客户 ...

  6. WPF 元素相对另外一个元素的 相对位置

    原文:WPF 元素相对另外一个元素的 相对位置 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/koloumi/article/details/740 ...

  7. P和P1指向了O和O1两个变量(对象)的地址, 而不是O和O1的内容(对象的实际地址)——充分证明@是取变量(对象)的地址,而不是变量里面的内容,够清楚!

    如图,为什么这样取出来的p,p1的值不一样呢?   165232328群友庾伟洪告诉我:  P和P1指向了O和O1两个变量(对象)的地址, 而不是O和O1的内容(对象的实际地址) ,你想P指向真正的对 ...

  8. 阿里将成为下一个谷歌?是谁Google真正的挑战者

    非常多观点觉得阿里下一步即将成为google的挑战者,但不管从技术储备还是产业布局来看,阿里都难当此任.在产业模式上.电商挑战搜索尚有诸多短板,在解决这些根本问题前,空泛谈论这些是没有意义的. < ...

  9. js 操作样式

    <!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  10. 调用其它UI文件

    调用其它UI文件 首先 要头文件包含  #include “dialog_biaozhun.h"Dialog_biaozhun *dialog = new Dialog_biaozhun() ...