Linux动态链接库

一、背景

我们使用Linux的过程中,例如安装程序或者部署一些如Python等,可能会遇到过如下动态链接库(共享库)报错:

ImportError: libcrypto.so.10: cannot open shared object file: No such file or directory

bash 复制代码
$"./lib/python3.8/lib/python3.8/ssl.py", line 98, in <module> import _ssl 
# if we can't import it, let the error propagate ImportError: 
libcrypto.so.10: cannot open shared object file: No such file or directory

例如这里的是报错,libcrypto.so.10 动态库没找到.

那我们来分析一下,Linux动态链接库的一个查找过程是怎么样的。为什么说没找到这个文件呢? 寻找的过程是怎么样的

二、动态链接库、共享库

1、定义

在 Linux 系统中,动态链接库(Dynamic Link Library)和共享库(Shared Library)是指同一概念的不同称谓,通常指的是 .so(shared object)文件。这类库在 Linux 和其他类 Unix 操作系统中非常常见,用于实现程序的模块化和资源的共享。

动态链接库/共享库 是一种二进制文件,其中包含了一组预先编译好的函数和数据结构,可以被多个不同的程序共享。这些库通常在程序运行时被加载,并且可以被多个进程同时使用。

在 Linux 中,动态链接库通常以 .so 扩展名命名,例如 libfoo.so。这个扩展名表明这是一个共享对象文件,它可以被动态链接器加载。

Redhat系列一般存放于: /usr/lib/、/usr/lib64/ , 同时 / 下存在lib和lib64的软链接到/usr/lib、/usb/lib64/

Linux中命名系统中共享库的规则:

如文章开头缺失的共享库的名称就是crypto

2、寻找so动态链接库的过程

1、首先查找当前环境中,环境变量LD_LIBRARY_PATH路径(多路径使用:分隔,和定义PATH环境变量路径一样),依次遍历,查找是否存在libcrypto.10.so这个文件,存在则读取,停止搜索,否则继续往下执行

2、查找/etc/ld.so.cache已经缓存好的所有so动态库的路径,查看是否存在里面。存在则加载,否则查找so文件失败,程序报错. 我看可以看看/etc/ld.so.cache是什么东西? 这个是ldconfig根据/etc/ld.so.conf配置文件配置的共享库查找路径,预先查找到所有的so,记录了这些so的绝对路径形成的一个列表二进制文件(不能直接用cat打开, 使用strings打开查看内容).例如我们使用strings查看/etc/ld.so.cache文件内容:

ld.so.cache文件缓存好了查找/etc/ld.so.conf配置好的搜索动态库路径搜索到所有so的绝对路径。

这样应用程序查找的时候就没必要再次全量扫描/etc/ld.so.conf的路径下有没有对应的so了,直接从/etc/ld.so.cache匹配一下,效率更高、查找速度更快。

3、ldconfig、LD_LIBRARY_PATH、ldd命令的用处

1、ldconfig命令,重新生成/etc/ld.so.cache缓存

1、直接执行ldconfig会重新生成/etc/ld.so.cache缓存文件,一般用于,新添加了/etc/ld.so.conf搜索so的路径,需要重新生成缓存

2、ldconfig -p 查看当前缓存so路径内容, 类似strings /etc/ld.so.cache的效果

2、LD_LIBRARY_PATH 环境变量

ldconfig适用于全局的so查找路径。 但是因为作为全局,一般兼容性高,很少存在版本冲突问题。 如果我们应对的是相同的共享库,但是是这个共享库的不同版本。 例如我的A程序依赖于ssl的v1版本,但是系统依赖的是ssl的v2版本等等。 这就蛋疼了, 那这个ssl库保留哪个版本呢? 单独保留某一个版本,都无法满足需求。 要操作系统依赖的存在问题、要么应用程序存在问题。

所以,Linux提供给我们这个LD_LIBRARY_PATH环境变量,就是解决这种多版本问题。 可以作为临时设置so查找的路径,这样可以避免版本冲突以及查找优先级.

例如设置export LD_LIBRARY_PATH=/my/v1/:$LD_LIBRARY_PATH, 先把自己A程序查找共享库的路径放到前面,其它放在后面,那么一旦从我们的v1找到,就停止搜索了,后面v2的ssl.so就不会被搜索到了.

1、提高so共享库查找的优先级

2、可以解决版本冲突问题

3、ldd命令,查看一个二进制命令依赖共享库的信息

有时候我们关于共享库报错,那么我们想看下这个二进制是缺的什么共享库,用到了哪些共享库。 可以使用 ldd $程序二进制绝对路径查看,例如查看ssh命令的共享库依赖:

从ldd结果,如果某些库找不到,那么我们需要通过yum或者其他方式安装对应这个库依赖即可解决问题

4、回到案例,排查结果

我们知道了动态库的原理,那么针对文章开头的地方,我们去看了一下确实存在问题。 libcrypto.so.10软连接指向的源文件,路径搞错了,导致找不到文件:

源文件路径多了空格,并且源文件路径不存在。 导致应用程序查找到了.so,但是无效的软链接,所以报错。

三、总结

下次遇到动态链接库报错、多版本的so共享库不必慌张,原理就是如此。希望对大家有所帮助!

相关推荐
林姜泽樾19 分钟前
Linux入门第十二章,创建用户、用户组、主组附加组等相关知识详解
linux·运维·服务器·centos
zyq99101_125 分钟前
优化二分查找:前缀和降复杂度
数据结构·python·蓝桥杯
qyzm28 分钟前
天梯赛练习(3月13日)
开发语言·数据结构·python·算法·贪心算法
xiaokangzhe1 小时前
Linux系统安全
linux·运维·系统安全
feng一样的男子1 小时前
NFS 扩展属性 (xattr) 提示操作不支持解决方案
linux·go
xiaokangzhe1 小时前
Nginx核心功能
运维·nginx
松果1771 小时前
以本地时钟为源的时间服务器
运维·chrony·时间服务器
Highcharts.js2 小时前
Highcharts React v4.2.1 正式发布:更自然的React开发体验,更清晰的数据处理
linux·运维·javascript·ubuntu·react.js·数据可视化·highcharts
Qt学视觉2 小时前
AI2-Paddle环境搭建
c++·人工智能·python·opencv·paddle
ayaya_mana2 小时前
快速安装Nginx-UI:让Nginx管理可视化的高效方案
运维·nginx·ui