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共享库不必慌张,原理就是如此。希望对大家有所帮助!

相关推荐
weixin_468466851 天前
遗传算法求解TSP旅行商问题python代码实战
python·算法·算法优化·遗传算法·旅行商问题·智能优化·np问题
橘子真甜~1 天前
C/C++ Linux网络编程2 - Socket编程与简单UDP服务器客户端
linux·运维·服务器·网络编程api·udp协议·udp通信
深圳市恒讯科技1 天前
服务器与普通个人电脑的主要区别是什么?
运维·服务器
qq_281317471 天前
nginx安装配置、故障处置、性能优化
运维·nginx
Nina_7171 天前
pytorch核心组件以及流程
人工智能·pytorch·python
Highcharts.js1 天前
在Python中配置高度交互的数据可视化:Highcharts完全指南
开发语言·python·信息可视化·highcharts
Ace_31750887761 天前
京东关键字搜索接口逆向:从动态签名破解到分布式请求调度
分布式·python
未来之窗软件服务1 天前
服务器运维(十一)SQLite3 php封装——东方仙盟炼气期
运维·服务器·sqlite·服务器运维·数据库驱动·东方仙盟
QT 小鲜肉1 天前
【QT/C++】Qt样式设置之CSS知识(系统性概括)
linux·开发语言·css·c++·笔记·qt
yachuan_qiao1 天前
专业的建筑设备监控管理系统选哪家
大数据·运维·python