Linux共享库的组织 -- 学习笔记

8.1  共享库的版本

共享库的更新可以被分为两类:

兼容更新。所有的更新只是在原有的共享库基础上添加以内容,所有原有的接口都保持不变

不兼容更新,共享库更新改变了原有的接口,使用该共享库原有接口的程序可能不能运行或运行不正常

这里讨论的接口是二进制接口,ABI

导致C语言的共享库ABI改变的行为主要有4个:

1) 导出函数的行为发生改变

2) 导出函数被删除

3) 导出数据的结构发生变化

4) 导出函数的接口发生变化,如函数返回值、参数被改变

共享库版本命名:

Linux有一套规则链命名系统中的每一个共享库,libname.so.x.y.z

“x”表示的主版本号,"y"表示次版本号,"Z"表示发布版本号

SO-NAME

Solaris和Linux系统都采用一种叫做SO-NAME的命名机制来记录共享库的依赖关系,每一个共享库都会有一个对应的“SO-NAME”,这个SO-NAME就是共享库去掉次版本号和发布版本号,只保留主版本号的名字

Linux系统中,系统会为每个共享库在它所在的目录创建一个“SO-NAME”的指向共享库的软链接

建立以“SO-NAME”为名字的软连接的目的是:使得所有依赖于某个共享库的模块,在编译、链接和运行时,都是用共享库的SO-NAME,而不使用详细的版本号

Linux中提供了一个工具叫做“ldconfig”,当系统中安装或更新一个共享库时,该工具会创建或者更新软连接指向这个共享库

8.2  符号版本

Linux中的符号版本

Linux系统下的共享库的符号版本机制并没有被广泛使用,主要使用于Glibc软件包中所提供的20多个共享库。

这些共享库比较有效地利用了符号版本机制来表示符号的版本演化机利用范围机制来屏蔽一些不希望暴露给共享库使用者的符号

Linux系统下共享库符号版本机制并没有被广泛应用,主要使用共享库符号版本机制的是Glibc软件包中所提供的20多个共享库

GCC允许使用一个叫做“.symver”的汇编宏指令来指定符号的版本,这个宏汇编指令可以被用在GAS汇编中,也可以在GCC的C/C++源代码中以嵌入式汇编指令的模式使用

asm(“ .symver  add , [email protected]_1.1”)

int add(int a,int b)

{

return a + b;

}

GCC 允许多个版本的同一符号存在于一个共享库中,也就是说,在链接层面提供了一种符号重载的机制,如下:

asm(" .symver  old_printf,  [email protected]_1.1")

asm(" .symver  new_printf, [email protected]_1.2")

int old_printf(){ …… }

int new_printf(){ …… }

在Linux下,当我们使用ld链接一个共享库时,可以使用“--version-script”参数,如果使用GCC,则可以使用“-Xlinker”参数加“--version-script”,相当于把“--version-script”传递

给ld链接器

gcc  -shared -fPIC lib.c -Xlinker  --version-script lib.ver -o lib.so

VERS_1.2{

global:

     foo;

local:

*;

}

8.3  共享库的系统路径

Linux 系统遵守FHS标准,FHS规定,一个系统中主要有3个存放共享库的位置

/lib,/usr/lib   ,/usr/local/lib

程序所以来的共享对象全部由动态连接器负责装载和初始化

动态连接器对于模块的查找有一定的规则,如果DT_NEED里面保存的是绝对路径,那么动态链接器就按照这个路径去查找,如果DT_NEED里面保存的是相对路径,那么动态连接器会在/lib

/usr/lib和由/etc/ld.so.conf 配置文件指定的目录中查找共享库

Linux系统中都有一个叫做ldconfig的程序,这个程序除了会将共享目录下的共享库创建、删除或更新相应的SO-NAME外,还会将这些SO-NAME收集起来,集中存放到/etc/ld.so.cache文件里,建立一个SO-NAME的缓存

如果动态连接器在/etc/ld.so.cache里面没有找到所需要的共享库,那么它还会遍历/lib和/usr/lib 这两个目录

8.4  环境变量

LD_LIBRARY_PATH

Linux系统提供了 LD_LIBRARY_PATH 环境变量可以用于改变共享库查找路径,这个方法可以临时改变某个应用程序的共享库查找路径,而不会影响系统中的其他程序

在Linux系统中,LD_LIBRARY_PATH 是一个由若干路径组成的环境变量,每个路径之间由冒号隔开

动态连接器会按照如下顺序依次装载或查找共享对象:

由环境变量LD_LIBRARY_PATH 指定的路径

由路径缓存文件/etc/ld.so.cache指定的路径

默认共享库目录,先/usr/lib,然后/lib

LD_PRELOAD

系统中还有一个环境变量叫做LD_PRELOAD,这个环境变量文件中我们可以指定预先装载的一个共享库或者是目标文件

比LD_LIBRARY_PATH优先     LD_PRELOAD 里面指定的共享库或目标文件都会被装载

由于全域符号介入的机制存在,LD_PRELOAD 里执行的共享库或目标文件中的全局符号就会覆盖后面加载的同名全局符号,这使得我们可以很方便地坐到改写标准的C库中的某个或某几个函数而不影响其他函数,对于程序的测试或者调试非常有用

系统配置文件中有一个文件时/etc/ld.so.preload  它的作用与LD_PRELOAD 一样。这个文件里面记录的共享库或目标文件的效果LD_PRELOAD里指定的一样

LD_DEBUG

这个变量可以打开动态链接器的调试功能,当我们设置这个变量时,动态链接器会在运行时打印出各种有用的信息,对于我们开发和调试共享库有很大的帮助

LD_DEBUG可以设置很多值:

files    动态链接器会打印出整个装载过程,显式程序所依赖于哪些共享库并按照什么步骤装载和初始化,共享库装载时的地址

bindings    显示动态链接的符号绑定过程

libs  显示共享库的查找过程

versions   显示符号的版本依赖关系

reloc  显示重定位过程

symbols   显示符号表查找过程

statics  显示动态链接过程中的各种统计信息

all  显示以上所有信息

help   显示上面的各种可选值的帮助信息

8.5  共享库的创建

创建共享库的过程跟创建一般的共享对象的过程基本一致,最关键的是使用GCC的两个参数,即“-shared”和 "-fPIC" “-shared”表示输出的结果是共享库类型的,“-fPIC”表示使用地址无关代码来产生输出文件。另外还有一个参数是“-W1”参数,这个参数可以将指定的参数传递给链接器,比如:我们使用“-W1,-soname,-my_soname”时,GCC会将“-soname my_soname”传递给链接器

ld的参数 “-rpath”选项可以指定链接器产生目标程序的共享库查找路径,比如我们使用如下命令行产生一个可执行文件

ld -rpath  /home/mylib   -o programe.out  programe.o -lsomelib

ld链接器提供了一个“-export-dynamic”的参数,这个参数表示链接器在生产可执行文件时,将所有全局符号到处到动态库符号表

清除符号信息:

使用strip工具,可以清除共享库或者可执行文件的所有符号和调试信息

strip  libfoo.so

共享库的安装

创建共享库以后我们必须将它们安装在系统中,以便各种程序都可以共享它,最简单的方法就是将共享库复制到某个标准额共享库目录,如:/lib 、/usr/lib等,然后运行ldconfig即可

共享库构造和析构函数

GCC提供了一种共享库的构造函数,只要在函数声明时加上“__arttribute__(construcor)”的属性,即指定该函数为共享库的构造函数,拥有这种属性的函数会在共享库加载时被执行,即在程序的main函数之前执行,

与共享库相对应的是析构函数,我们可以在使用的函数声明时加上“__attribute__(destructor)”的属性,这种函数会在main()函数执行完毕之后执行

声明构造函数和析构函数的格式如下:

void __attribute__((constructor)) init_function(void);

void __attribute__((destructor)) fini_function();

GCC为我们提供了一个参数叫做优先级,我们可以指定某个构造函数或析构函数的优先级:

void __attribute__((constructor(5)))  init_funciton1(void);

void __attribute__((constructor(10))) init_function2(void);

时间: 2024-10-07 08:57:33

Linux共享库的组织 -- 学习笔记的相关文章

linux共享库

linux共享库 linux中共享库一般以.so.x.y.z 命名,其中x,y,z分别为主版本号.次版本号.发布版本号.同一个库,主版本号不同则相互不兼容:主版本相同,次版本号高的库比次版本号低的库有一些更新,增加了一些接口符号且保持原来的接口符号不变,但保持后向兼容:主版本号和次版本号相同,发布版本号不同,表示库的一些修改修正,不增加新功能. SO-NAME软链接 SO-NAME 软链接:共享库 libname.so.x.y.z 的SO-NAME软链接命名为 libname.so.x 即去掉次

微软企业库5.0学习笔记(10)ASP.NET模块依赖注入

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样. 下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件.当OnPageIni

Linux 共享库(动态库)

Linux 系统上有两类根本不同的 Linux 可执行程序.第一类是静态链接的可执行程序.静态可执行程序包含执行所需的所有函数 - 换句话说,它们是"完整的".因为这一原因,静态可执行程序不依赖任何外部库就可以运行. 第二类是动态链接的可执行程序. 静态可执行程序与动态可执行程序比较 我们可以用 ldd 命令来确定某一特定可执行程序是否为静态链接的: # ldd /sbin/sln not a dynamic executable "not a dynamic executa

linux环境 :Linux 共享库LIBRARY_PATH, LD_LIBRARY_PATH 与ld.so.conf

参考: 1. Linux 共享库:LD_LIBRARY_PATH 与ld.so.conf Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默认路径之前查找) 移植程序时的经常碰到需要使用一些特定的动态库,而这些编译好的动态库放在我们自己建立的目录里,这时可以将这些目录设置到LD_LIBRARY_PATH中. 当执行函数动态链接.so时,如果此文件不在缺省目录下‘/usr/local/lib’ and ‘/usr/lib’. 那么就需要指

Linux共享库路径配置

今天在某测试服务器上使用ab压力测试工具时,出现了错误 ab: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory 查询资料,发现原因是是找不到正确的共享库路径. 参考资料: Linux共享库路径配置 /etc/ld.so.conf文件 解决方法: 1.添加搜索路径,并使用ldconfig命令更新. 查看/etc/ld.so

linux 共享库版本管理

原理 请看Linux 如何解决共享库的版本控制 我的理解 linux在系统内部将用到的共享库版本都保留下来,并没有覆盖.(不同soname) 调用程序和共享库在链接的时候已经记录下来了共享库的soname. libxx.so文件一般只是一个软链接.只是为了与gcc命令参数-lxx 中的xx名称一致.实际中可以在不同目录创建相同名字的libxx.so链接到不同soname的共享库.gcc -lxx使用-L参数指定不同目录位置,实现使用不同版本的共享库链接.在链接完成之后,libxx.so就失去了他

windows动态链接库[DLL]与Linux共享库[SO]技术浅析

一.动态链接库的技术优点: 1)节省内存和磁盘空间:因为动态库在内存或磁盘中只需一份,便可供多个进程或程序使用. 2)模块化编程,方便协作:这一点静态库也能胜任. 3)使用动态加载DLL或SO时,便于模块升级,无需重新编译或链接整个程序. 二.windows的动态链接库: 1.windows的静态库生成的是.lib文件,其中包含了函数和数据实体,链接时合到程序中: 2.windows的动态库生成.dll文件并导出一个.lib文件,该.lib文件中的函数没有实体[不是一个 准确的说法],函数内部是

Linux共享库.so文件的命名和动态链接

Linux中的.so文件 是动态链接的产物 共享库理解为提供各种功能函数的集合,对外提供标准的接口 Linux中命名系统中共享库的规则 主版本号:不同的版本号之间不兼容 次版本号:增量升级 向后兼容 发行版本号:对应次版本的错误修正和性能提升,不影响兼容性 Linux中的共享库并不都是这样的格式 比如GLibc的共享库命名为:libc-x.y.z.so 动态链接器也是GLibc的一部分,使用ld-x.y.z.so命名 libm(数学库)等 SO-NAME机制 系统和程序中要链接的共享库的格式一般

Linux Linux共享库

so文件在linux中为共享库,与windows下的dll类似. so文件中的函数可供多个进程调用,最大可能的提供二进制代码复用. 共享库可以使代码的维护工作大大简化,当修正了一些错误或者添加了新特性的时候,用户只需要获得升级后的so并安装他就可以. 注意:即使不同的进程调用同一个so文件,通过共享库并不能实现不同进程间的通讯,因为同一个so被不同进程加载到不同的内存空间. so文件编译方法 --so文件的源文件中不需要main函数,即使有也不会被执行. --编译的时候gcc需要加-fPIC选项