工作问题经验整理——带版本号so库文件含义和主程序链接so库机制

Posted yxtxiaotian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工作问题经验整理——带版本号so库文件含义和主程序链接so库机制相关的知识,希望对你有一定的参考价值。

一、(20190412)

1、问题描述

库的生成:项目工程 TestProj 中使用zlog开源日志库,使用两种方式编译生成so库:

  • A:使用源码中自带makefile进行编译,会产生 libzlog.a/libzlog.so/libzlog.so.1/libzlog.so.1.1(A) 四个文件;
  • B:通过zlog 中的源码文件,自己在 eclipse 中创建 生成so库 的项目工程 zlog,配置将要生成的so库的后缀为 so.1.1,配置位置无关属性,生成 libzlog.so.1.1(B) 日志库;

问题产生过程:

  • 将A步骤产生的 libzlog.so.1.1(A) 文件拷贝到 TestProj 项目工程中在lib目录下面之后,修改名字为 libzlog.so;链接工程生成 TestProj(A) 可执行程序;将 A步骤产生的 libzlog.so.1.1 文件 和 TestProj(A) 一起放到linux系统中运行,正常运行;
  • 将B步骤产生的 libzlog.so.1.1(B) 文件拷贝到 TestProj 项目工程中在lib目录下面之后,修改名字为 libzlog.so;链接工程生成 TestProj(B) 可执行程序;将 B步骤产生的 libzlog.so.1.1 文件 和 TestProj(B) 一起放到linux系统中运行,运行异常,提示找不到 libzlog.so 库文件;

相关说明:

  • 这里项目工程TestProj 中使用了 libzlog.so.1.1这种带数字版本后缀的库的原因,是因为一开始在项目工程中引入不带后缀的libzlog.so 库,TestProj运行的时候会报找不到 libzlog.so.1.1 库文件,所以后面工程直接使用了 libzlog.so.1.1 库;同时在自己编译的版本中也修改库后缀名称为 so.1.1,也是为了 兼容原来版本;
  • 将libzlog.so.1.1库文件拷贝到 项目工程TestProj 的lib目录之后需要修改库名字为 libzlog.so 这种不带后缀的原因,是因为 带后缀的库,项目工程在进行链接的时候会找不到库文件;

2、问题分析

相同项目工程TestProj ,工程目录下库名字也都改为libzlog.so,但是链接生成的TestProj(A)正常运行,TestProj(B)则运行异常;查看2个可执行程序TestProj(A) 和 TestProj(B) 的库依赖, 如下(结果作了部分敏感信息处理):

从上图可执行程序TestProj(A) 和 TestProj(B) 的zlog库依赖关系可以看出:

  1. TestProj(A)依赖的是 libzlog.so.1.1文件,所以上面 将 A步骤产生的 libzlog.so.1.1(A) 文件 和 TestProj(A) 一起放到linux系统中运行,正常运行,因为在TestProj(A)运行时可以找到一起拷贝进来的名字为libzlog.so.1.1的库;
  2. TestProj(B)依赖的是 libzlog.so文件,所以上面 将 B步骤产生的 libzlog.so.1.1(B) 文件 和 TestProj(B) 一起放到linux系统中运行,运行异常,会提示找不到 libzlog.so 库文件,因为一起拷贝进来的库的名字是libzlog.so.1.1 ;

那么问题来了,相同项目工程TestProj ,工程目录下库名字也都改为libzlog.so,为什么TestProj(A) 会链接到 libzlog.so.1.1,而TestProj(B) 会链接到  libzlog.so ??或者说,TestProj链接so动态库的内部机制是怎样(这个在后面章节讲解)??现在进一步思考,唯一的不同只有 libzlog 库的来源不同,TestProj(A) 中使用的libzlog.so是使用自带的makefile编译出来的libzlog.so.1.1(A),进一步修改名字得到;而TestProj(B) 中使用的libzlog.so是使用自己创建的zlog动态库工程编译出来的libzlog.so.1.1(B),进一步修改名字得到。

进一步,查看 libzlog.so.1.1(A) 和 libzlog.so.1.1(B) 库文件内部信息和依赖,如下:

从上图 libzlog.so.1.1(A) 和 libzlog.so.1.1(B) 库文件内部信息可以看出:

  • libzlog.so.1.1(A) 中有指定[SONAME]为Library soname: [libzlog.so.1.1];
  • 而 libzlog.so.1.1(B) 虽然库文件名称也是 so.1.1 后缀,但这个后缀是我们在创建zlog动态库工程的时候指定的编译生成动态库的后缀名称,实际并没有在库内部生成[SONAME]信息。

所以分析得到,虽然在相同项目工程TestProj ,工程目录下库名字也都改为libzlog.so,但是 来源不同的 "libzlog.so" ,其内部[SONAME]信息不同, 导致TestProj工程实际链接的依赖库名字不同,在TestProj 运行的时候,会根据链接时候的库名字也即[SONAME]信息,在linux系统指定的库目录(/lib)中查找对应名称的库文件。

3、解决方案

  •  如果使用了TestProj(A)程序,就把 libzlog.so.1.1(A) 一并拷贝进系统,正常运行;
  • 如果使用了TestProj(B)程序,就把 libzlog.so.1.1(B) 修改名字为 libzlog.so 不带后缀,正常运行。

4、进一步提出问题:链接so动态库的内部机制是怎样??

[SONAME]字段信息是什么?TestProj工程链接时是因为使用该信息作为链接库名字,且在TestProj工程实际运行的时候使用了该链接名称进行动态库so的查找么?应用程序逻辑so动态库的内部机制是怎样?so动态库带有的后缀数据版本信息 又代表什么意义?下面我们一一来解决这些问题。

 

二、应用程序链接so动态库的内部机制

1、

 

 

以上是关于工作问题经验整理——带版本号so库文件含义和主程序链接so库机制的主要内容,如果未能解决你的问题,请参考以下文章

工作问题经验整理——在so库中日志写到主程序日志文件

linux内核版本分别带表啥含义?

libcurl库编译生成不带版本的设置方法

Linux获取so/ko文件版本号教程

Qt creator交叉编译带图片的程序出现问题,版本4.7

带工作流的springboot后台管理项目,一个企业级快速开发解决方案