Linux中共享库(so)的几个名称及相关用法

本文主要介绍在Linux操作系统中,同一个共享库(so)的几个名字,以及这几个名字的应用场景。

1 概述

本文从共享库(so)的版本控制角度来讲述。本文会以 curl 共享库 libcurl 为例,来展开讲述。

首先在此说明,so有三个名字,如下:

  • realname:so的真实名称,如 libcurl.so.4.5.0
  • soname:so的软链接名称,如 libcurl.so.4
  • linkername:编译过程中使用的so的名称,如 curl

2 realname

realname是so的真实名称,如编译安装curl软件后,生成的 /usr/local/lib/libcurl.so.4.5.0。

realname在文件名中带有版本号信息,如 libcurl.so.4.5.0 的“4.5.0”。

3 soname

从版本控制的脚本来看,如果一个可执行程序直接连接到so的realname,那么当该so升级的时候,so的版本号发生了变化,那么就必须重新编译生成该可执行程序,这显然是不好的版本管理方式。为了解决此问题,出现了so的soname。soname实际上是realname的一个软链接,我们可以通过“readelf -d”命令查看so的soname,如下:

soname一般会保留so的大版本号,如 libcurl.so.4。

在编译生成程序(可执行程序及共享库)时,我们通常都是连接的soname,这样当被依赖的so升级时,由于soname并没有变化,只需要将soname指向新的realname,即可实现被依赖的so的升级了,如此就实现了so的版本控制。

4 linkername

linkername是编译代码时的连接阶段使用的so的名字,实际上linkername也是指向realname的。

一般在程序编译时,我们会通过 -l 选项为其指定需要连接的so的名字(或是使用CMakeLists.txt时,为其指定的so的名字),样式类似:

-lcurl

或对应CMakeLists.txt中的“target_link_libraries(目标程序 ... curl ...)”,这里的 curl 就是so的linkername。

5 so的三个名称之间的关系

在编译生成程序时使用linkername进行连接的,而这个linkername实际上是指向 realname 的,但是在后续的使用过程中,程序其实是使用 soname 来找到被依赖的 realname 的,那么这三者是如何在编译、使用过程中连接起来的呢?

原来在编译生成 realname 时,已经为其指定了对应的 soname (如前文所述,可通过“readelf -d”来查询),这样以 soname 作为桥梁,即可将so的三个名称联系起来。

结合程序的编译、生成、运行过程,描述so的三个名称关系如下:

1. 程序编译时,用到了依赖库的so的 linkername,即 curl,由于 linkername 指向 realname,所以程序实际上连接到了 realname;

2. 程序从 realname 处获取到运行时需要用到的 soname,即 libcurl.so.4;

3. 编译生成程序;

4. 程序运行时,调用 soname,而 soname 实际上又指向了 realname,所以程序实际上是调用的 realname。

上述几个步骤可以使用下图来表述:

猜你喜欢

转载自blog.csdn.net/liitdar/article/details/81279594