ubuntu-c++-可执行模块-动态链接库-链接库搜索-基础知识

文章目录

1.动态链接库简介

动态库又叫动态链接库,是程序运行的时候加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。动态库是目标文件的集合,目标文件在动态库中的组织方式是按特殊的方式组织形成的。在动态库中函数和变量的地址是相对地址而不是绝对地址,其真实地址在调用动态库的程序加载时形成的。

动态库的名字有别名(soname), 真名(realname)和链接名(linkername)。别名是由一个lib前缀,然后是库的名字,最后以".so"结尾来构成。真名是动态链接库的真实名字,一般总是在别名的基础上添加一个版本号信息。除此之外还有一个链接名,他是在程序链接的时候使用的名字。

动态库安装的时候,总是复制库文件到某一个目录,然后使用一个软链接生成一个别名,在库文件更新的时候,仅仅更新软链接即可。

2.动态库搜索路径

(仅对ELF格式)如果可执行文件包含DT_RPATH标签,并且不包含DT_RUNPATH标签,将从DT_RPATH列出的路径搜索。(DT_RPATH已经被废弃,请用DT_RUNPATH)

如果LD_LIBRARY_PATH在程序运行时被定义,那么将从它包含的路径开始。安全起见,对于set-user-ID或者set-group-ID的程序,这个变量将被忽略。

(仅对ELF格式)如果可执行文件包含DT_RUNPATH标签,将从这个标签列出的路径开始搜索。

从 /etc/ld.so.cache(运行ldconfig产生)中查找文件

从/lib以及/urs/lib,按顺序搜索。如果链接时指定-z nodefaultlib,这个步骤将被忽略。

3.运行时链接及搜索顺序

这个过程是由ld-linux.so程序来执行,这个才是真正的链接。它所做的工作就是将动态库的代码映射到进程的虚拟地址空间中,供进程来调用。程序在连接时使用了共享库,就必须在运行的时候能够找到共享库的位置。linux的可执行程序在执行的时候默认是先搜索/lib和/usr/lib这两个目录,然后按照/etc/ld.so.conf里面的配置搜索绝对路径。同时,Linux也提供了环境变量LD_LIBRARY_PATH供用户选择使用,用户可以通过设定它来查找除默认路径之外的其他路径,LD_LIBRARY_PATH路径优先于系统默认路径之前查找。

LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找!!(看到Qt的使用qmake生成的makefile中,有gcc -rpath xxx,指出程序运行时的一个搜索路径, 或许与qt的QMAKE_RPATHDIR有关)

ld-linux.so.x在可执行的目标文件中被指定,可用readelf -l命令查看 。

(很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所 需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.x来负责完成的)

和Windows下的PE文件类似,ELF文件是linux系统下可执行文件、动态库文件、静态库文件的标准格式。

例如,运行readelf -l 文件名,在输出的Headers部分的INTERP部分,会指出该可执行文件需要的ld-linux.so

运行时,ld-linux.so 查找共享库的路径:

(1)编译时使用gcc的-R或-rpath选项指定路径。

(2)LD_LIBRARY_PATH环境变量中所设定的路径。

(3)ld-linux.so 缺省在/usr/lib和/lib中搜索;当glibc安装到/usr/local下时,它查找/usr/local/lib

(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路径。 (查看/etc/ld.so.conf文件:或许只有一行:"include /etc/ld.so.conf.d/*.conf ",意味着包括了/etc/ld.so.conf.d/目录下的所有.conf文件,每个文件中都写着具体的路径。如果你想加一个运行时的搜索路径,可在/etc/ld.so.conf.d目录下新建一个.conf文件,里面写上路径,注意添加完了之后要在root权限下运行ldconfig指令,使其生效,该指令更新记录了系统中有哪些so文件的缓存文件(/etc /ld.so.cache)。)

4.查看可运行模块的链接库

可使用ldd指令查看一个可执行文件依赖于哪些库:ldd xxx

powershell 复制代码
ldd  bash

linux-vdso.so.1是Linux为了解决和glibc兼容而想出的绝招。

原来这个 linux-vdso.so.1 文件,并不是一个真实存在的文件,而是 Linux 中的一个虚拟文件,专门用于将内核中一些常用的函数从内核空间映射到用户空间。也就是说,这个文件不用复制。

VDSO就是Virtual Dynamic Shared Object,就是内核提供的虚拟的.so,这个.so文件不在磁盘上,而是在内核里。内核把包含某.so的内存页在程序启动的时候映射入其内存空间,对应的程序就可以当普通的.so来使用其提供的函数接口。

5.总结

在linux下的动态链接库并不从程序所在当前目录查找连接库,而是从编译时指定目录查找,或者默认目录查找。

相关推荐
Lary_Rock36 分钟前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
云飞云共享云桌面3 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
一坨阿亮4 小时前
Linux 使用中的问题
linux·运维
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
dsywws5 小时前
Linux学习笔记之vim入门
linux·笔记·学习
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
捕鲸叉6 小时前
MVC(Model-View-Controller)模式概述
开发语言·c++·设计模式