ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

共享库的版本控制

2022-08-02 19:32:19  阅读:168  来源: 互联网

标签:版本控制 so.1 libadd 兼容 int add 版本 共享


共享库的版本控制

关于 SONAME

编译动态库时,可以指定 SONAME 。程序运行时,加载器(Dynamic Loader)发现动态库有 DT_SONAME 字段,则会转而去链接 DT_SONAME 指定的动态库。

应用:库的版本

Linux 动态库的版本号一般格式为 lib + libname + .so + 主版本号 + 子版本号 + 发行版本号 。

情况一:如果版本号发生了改变之后,实际库仍然是兼容的,此时更新软链接,将主版本,即可实现库的更新。
情况二:如果版本号发生了改变之后(一般是主版本),库不再兼容,此时变更 SONAME ,即可实现库的多版本兼容(多个库同时存在,由程序根据 SONAME 选择加载)。

例子:

// add.c
// V1.0.0
int add(int a, int b)
{
    return a+b;
}
// main.c
#include<stdio.h>
int add(int a, int b);
int main()
{
    int a = 1;
    int b = 2;
    int c = add(a, b);
    printf ("c=%d\n", c);
    return 0;
}

对第一种情况:

版本更新前:

gcc add.c -shared -fPIC -Wl,-soname=libadd.so.1 -o libadd.so.1.0.0
ldconfig -nv .
ln -s libadd.so.1 libadd.so
gcc main.c -L. -ladd 
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./a.out

观察动态库和 a.out 的符号:

readelf -d libadd.so.1.0.0
Dynamic section at offset 0x2e80 contains 18 entries:
  Tag        Type                         Name/Value
 0x000000000000000e (SONAME)             Library soname: [libadd.so.1]

readelf -d a.out
Dynamic section at offset 0x2db0 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libadd.so.1]

也即,编译库的时候,生成的库的名字为最完整的名字(比如 libadd.so.1.0.0),库的 SONAME 字段为兼容版本的库名字(比如 libadd.so.1)。生成 a.out 时,链接的名字始终使用 -ladd ,也即需要创建一个 libadd.so 的链接指向兼容版本的库。最终生成 a.out 时,依赖的库的名字是根据 libadd.so 中的 SONAME 字段生成的(SONAME 字段存在时),也即 a.out 依赖的库名字为 libadd.so.1。

注意:libadd.so 只有编译生成 a.out 时需要使用(DEV)。如果只是部署,则只需要 libadd.so.1 和 libadd.so.1.0.0 就行了。

版本更新后(更新后仍然兼容,只更新子版本号):

rm libadd.1.*
gcc add.c -shared -fPIC -Wl,-soname=libadd.so.1 -o libadd.so.1.1.0
ldconfig -nv .

版本更新时,先删除当前已有的兼容版本,然后生成新的兼容版本,并利用 ldconfig 更新兼容版本链接。

ldconfig -nv .
.:
        libadd.so.1 -> libadd.so.1.1.0 (changed)

兼容版本更新过程中,需要删除已有版本。

对第二种情况:

// add.c
// V1.0.0
int add(int a, int b, int c)
{
    return a+b+c;
}
// main.c
#include<stdio.h>
int add(int a, int b, int c);
int main()
{
    int a = 1;
    int b = 2;
    int c = add(a, b, b);
    printf ("c=%d\n", c);
    return 0;
}

如果出现了库的不兼容版本更新,则两个库可以兼容存在。旧的程序链接旧版本的库,新的程序链接新版本的库,彼此互不干扰。

gcc add.c -shared -fPIC -Wl,-soname=libadd.so.2 -o libadd.so.2.0.0
ldconfig -nv .
ln -s libadd.so.2 libadd2.so
gcc main.c -L. -ladd2 -o a2.out
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./a2.out

这里我们把用于编译的库的名字做了区分(libadd.so 和 libadd2.so),这时为了编译的时候进行版本区分。

这样就实现了多个库的兼容。

标签:版本控制,so.1,libadd,兼容,int,add,版本,共享
来源: https://www.cnblogs.com/amazzzzzing/p/16544925.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有