引用自:http://www.linuxidc.com/Linux/2012-04/59071.htm

(换句话说,soname不是真实存在的文件,只是在此库中和将来调用此库的文件中保存的一个名字,在加载时去找这个名字,使用时创建一个软连接来指向真实文件,这样真实文件的版本号就可以升级了)

Linux 系统,也同样面临和Window一样的问题,如何控制动态库的多个版本问题。Window之前没有处理好,为此专门有个名词来形容这个问题 “Dll hell”,其严重影响软件的升级和维护。 Dll hell 是指windows 上动态库新版本覆盖旧版本,但是却不兼容老版本。常常发生在程序升级之后,动态库更新,原有程序运行不起来;或者装新软件,但是已有的软件运行不起来。 同样Linux操作系统,也有同样的问题,那么它是怎么解决的呢?

Linux 为解决这个问题,引入了一套机制,如果遵守这个机制来做,就可以避免这个问题。 但是这只事一个约定,不是强制的。但是建议遵守这个约定,否则同样也会出现 Linux 版的Dll hell 问题。 下面来介绍一个这个机制。 这个机制是通过文件名,来控制dll (shared library) 的版本。

Linux 上的Dll ,叫shared library,其有三个名字,分别有不同的目的。

第一个是共享库本身的文件名(real name),其通常包含版本号,常常是是这样: libmath.so.1.1.1234 。 lib是Linux 上的库的约定前缀,math 是共享库名字,so 是共享库的后缀名,1.1.1234的是共享库的版本号,其主版本号+小版本号+build号。主版本号,代表当前动态库的版本,如果动态库的接口有变化,那么这个版本号就要加1;后面的两个版本号(小版本号 和 build 号)是告诉你详细的信息,比如为一个hot-fix 而生成的一个版本,其小版本号加1,build号也应有变化。 这个文件名包含共享库的代码。

第二个是动态库的soname( Short for shared object name),其是应用程序加载dll 时候,其寻找共享库用的文件名。其格式为

lib + math+.so + ( major version number)

其只包含major version number,换句话说,也就是只要其接口没有变,应用程序都可以用,不管你其后minor build version or build version。

问题来了,程序运行时怎么通过soname 找个real name? Soname 存在哪里?如果与real name 关联起来?什么时候存的?

这就是接下来要介绍的第三个共享库的名字,link name,顾名思义,就是在编译过程,link 阶段用的文件名。 其将sonmae 和real name 关联起来。

第三个名字,共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。在共享库编译过程中,连接(link) 阶段,编译器将生成一个共享库及real name,同时将共享库的soname,写在共享库文件里的文件头里面。可以用命令 readelf -d sharelibrary 去查看。

在应用程序引用共享库时,其会用到共享库的link name。在应用程序的link阶段,www.linuxidc.com其通过link名字找到动态库,并且把共享库的soname 提取出来,写在自己的共享库的头文件里面。当应用程序加载时就会通过soname 去给定的路径下寻找该共享库。

下面通过这个代码来说明一下系统是如何做的,并且介绍系统的一些设施和工具:

代码:

1. File libhello.c
/* hello.c - demonstrate library use. */
#include <stdio.h>
void hello(void)
{ printf("Hello, library world./n");}
2. File libhello.h
/* libhello.h - demonstrate library use. */
void hello(void);
3. File main.c
/* main.c -- demonstrate direct use of the "hello" routine */
#include "hello.h"
int main(void)
{
hello();
return 0;
}
1.生成共享库,关联real name 和soname 。

gcc -g -Wall -fPIC -c hello.c -o hello.o

gcc -shared -W,soname,-libhello.so.0 -o libhello.so.0.0.0 hello.o

将会生成共享库libhello.so.0.0.0.

可以用系统提供的工具查看共享库的头:

readelf -d libhello.so.0.0.0 | grep libhello

ox00000000000e(SONAME)    library soname: [libhello.so.0]

2.应用程序,引用共享库。

先手动生成link 名字,以被后面的程序链接时用

ln -s libhello.so.0.0.0 libhello.so.0

gcc -g -Wall -c main.c -o main.o -I.

gcc  -o main main.o -lhello -L.

查看编译出来的程序:

readelf -d main | grep libhello

ox000000000001(NEEDED)    shared library: [libhello.so.0]

运行该程序,需要指定共享库的路径。 有两种办法,第一种使用环境变量“LD_LIBRARY_PATH”. 两外一种办法就是将共享库拷贝到系统目录(path 环境变量指定的其中一个目录)。

暂停! 我们还没有解决一个问题是,程序只知道soname,怎么从soname 找到共享库,即real name 文件呢? 这需要我们定义一个link文件,连接到共享库本身。

ln -s libhello.so.0.0.0 libhello.so.0

当然这个路径需要放到LD_LIBRARY_PATH环境变量中。

这样就可以运行该程序。

[Note]Linux 系统提供一个命令 ldconifg 专门为生成共享库的soname 文件,以便程序在加载时后通过soname 找到共享库。 同时该命令也为加速加载共享库,把系统的共享库放到一个缓存文件中,这样可以提高查找速度。可以用下面命令看一下系统已有的被缓存起来的共享库。

ld -p

Linux如何解决动态库的版本控制的更多相关文章

  1. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

  2. Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名

    Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf  动态库的后缀为*.so  静态库的后缀为 libxxx.a   ldconfig   目录名 转载自:http://b ...

  3. linux下so动态库一些不为人知的秘密(转)

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库, ...

  4. linux下so动态库一些不为人知的秘密

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.    基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些 ...

  5. linux下so动态库一些不为人知的秘密(上)

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.        基本上每一个linux 程序都至少会有一个动态库,查看某个程序使 ...

  6. 【转】分析Linux和windows动态库

    原文地址:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Lin ...

  7. linux静态与动态库创建及使用实例

    一,gcc基础语法: 基本语法结构:(由以下四部分组成) gcc -o 可执行文件名 依赖文件集(*.c/*.o) 依赖库文件及其头文件集(由-I或-L与-l指明) gcc 依赖文件集(*.c/*.o ...

  8. Linux和windows动态库

    转载:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 态链接库技术实现和设计程序常用的技术,在Windows和Linux系 统中 ...

  9. linux下so动态库一些不为人知的秘密(中二)

    继续上一篇< linux下so动态库一些不为人知的秘密(中) >介绍so搜索路径,还有一个类似于-path,叫LD_RUN_PATH环境变量, 它也是把路径编译进可执行文件内,不同的是它只 ...

随机推荐

  1. windows 64bit 服务器下安装32位oracle database 11g 问题集

    1.中文乱码 问题描述: 利用vs2008调试的时候正常,发布到IIS8.5上的时候,当查询语句中包含中文的时候会乱码,比如"select * from tb where name='小s' ...

  2. Java Socket 多线程聊天室

    本来这次作业我是想搞个图形界面的,然而现实情况是我把题意理解错了,于是乎失去了最初的兴致,还是把程序变成了功能正确但是“UI”不友好的console了,但是不管怎么样,前期的图形界面的开发还是很有收获 ...

  3. [转帖]PG里面的Citus简介----找时间学习一下.

    1. Citus是什么 是PostgreSQL的扩展,可以同PG一同安装,之后通过SQL命令加入到数据库中. [相关操作] ? 1 2 #创建Citus扩展: CREATE EXTENSION cit ...

  4. App phonegap

    云端打包 https://build.phonegap.com/apps phonegap PC端下载 https://www.phonegap.com/getstarted/ 移动端下载 https ...

  5. Spring IOC AOP的原理 如果让你自己设计IOC,AOP如何处理(百度)

    百度的面试官问,如果让你自己设计一个IOC,和AOP,如何设计, 我把IOC的过程答出来了,但是明显不对, (1) IOC 利用了反射,自己有个id,classtype,hashmap,所有的功能都在 ...

  6. Grafana elasticsearch 应用

    早期的时候,项目基于ES+echart写了一些仪表盘的展示页面,虽然ES配合这种char界面有着天然的优势,但实际写起代码来,还是很多重复的劳动,在一次偶然中发现Grafana,看到它提供了很多仪表盘 ...

  7. http——解读梳理

    (1)在客户端与服务器建立准确连接传输之前,先讲一讲三次握手 第一次握手:建立连接时,客户端发送syn包[同步序列编号(Synchronize Sequence Numbers).是TCP/IP建立连 ...

  8. P2704 [NOI2001]炮兵阵地

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  9. 51Nod 1384 全排列

    给出一个字符串S(可能有重复的字符),按照字典序从小到大,输出S包括的字符组成的所有排列.例如:S = "1312", 输出为:   1123 1132 1213 1231 131 ...

  10. caffe多任务、多标签

    解决的目标问题:多分类问题,比如车辆的外形和颜色,苹果的大小和颜色:多任务:车牌角点的定位和车牌的颜色.定位在技术上属于回归,车牌颜色判断则属于分类. 技术点 caffe默认是单输入任务单标签的,也就 ...