【链接装载与库】 Linux共享库的组织
Linux共享库的组织
由于动态链接的诸多优点,大量的程序开始使用动态链接机制,导致系统里面存在数量 极为庞大的共享对象。如果没有很好的方法将这些共享对象组织起来,整个系统中的共享对象文件则会散落在各个目录下,给长期的维护、升级造成了很大的问题。所以操作系统一般会对共享对象的目录组织和使用方法有一定的规则,我们将在这一章介绍Linux 下共享库的管理问题。
共享库版本
- 共享库兼容性
共享库的开发者会不停地更新共享库的版本,以修正原有的Bug、 增加新的功能或改进性能等。由于动态链接的灵活性,使得程序本身和程序所依赖的共享库可以分别独立开发和更新, 但是共享库版本的更新可能会导致接口的更改或删除,这可能导致依赖于该共享库的程序无法正常运行。最简单的情况下,共享库的更新可以被分为两类。
- 兼容更新。 所有的更新只是在原有的共享库基础上添加一些内容,所有原有的接口都 保持不变。
- 不兼容更新。 共享库更新改变了原有的接口,使用该共享库原有接口的程序可能不能 运行或运行不正常。
导致 C 语言的共享库ABI 改变的行为主要有如下4个
- 导出函数的行为发生改变,也就是说调用这个函数以后产生的结果与以前不一样。
- 导出函数被删除。
- 导出数据的结构发生变化,比如共享库定义的结构体变量的结构发生改变:结构成员 删除、顺序改变或其他引起结构体内存布局变化的行为
- 导出函数的接口发生变化,如函数返回值、参数被更改。
- 共享库版本命名
Linux 有一套规则来命名系统中的每一 个共享库,它规定共享库的文件名规则必须如下:
libname.so.x.y.z
最前面使用前缀“lib"、 中间是库的名字和后缀“.so”,最后面跟着的是三个数字组成 的版本号。“x”表示主版本号,“y”表示次版本号,“z” 表示发布版本号。 三个版本号的含义不一样。
主版本号表示库的重大升级,不同主版本号的库之间是不兼容的,依赖于旧的主版本号 的程序需要改动相应的部分,并且重新编译,才可以在新版的共享库中运行
次版本号表示库的增量升级,即增加一些新的接口符号,且保持原来的符号不变。在主 版本号相同的情况下,高的次版本号的库向后兼容低的次版本号的库。
发布版本号表示库的一些错误的修正、性能的改进等,并不添加任何新的接口,也不对接口进行更改。
- SO-NAME
共享库的主版本号和次版本号决定了一个共享库的接口。动态链接器怎样知道程序依赖于哪些共享库,它们的版本号又是什么?
Solaris 和Linux, 普遍采用一种叫做SO-NAME的命名机制来记录共享库的依赖关系。每个共享库都有一个对应的“SO-NAME”, 这个 SO-NAME即共享库的文件名去掉次版本号和发布版本号,保留主版本号。
系统会为每个共享库在它所在的目录创建一个跟 “SO-NAME” 相同的并且指向它的软链接
那么以“SO-NAME”为名字建立软链接有什么用处呢?
实际上这个软链接会指向目录 中主版本号相同、次版本号和发布版本号最新的共享库。
建立以SO-NAME为名字的软链接目的是,使得所有依赖某个共享库的模块,在编译、 链接和运行时,都使用共享库的SO-NAME,而不使用详细的版本号。
编译输出ELF文件时,将被依赖的共享库的SO-NAME保存到“.dynamic”中,这样当动态链接器进行共享库依赖文件查找时,就会根据系统中各种共享库目录中的SO-NAME软链接自动定向到最新版本的共享库。
Linux 中提供了一个工具叫做“ldconfig”, 当系统中安装或更新一个共享库时,就需要运行这个工具,它会遍历所有的默认共享库目录,比如/ib、/usr/ib 等,然后更新所有的软 链接,使它们指向最新版的共享库;如果安装了新的共享库,那么ldconfig会为其创建相应 的软链接。
符号版本
如果某个共享库在系统中存在相同主版本号不同次版本号的多个副本,那么动态链接器会使用那个最高次版本号的副本。如果找到的共享库次版本号低于所需要的版本, SunOS 4.x系统的策略是向用户发 出一个警告信息,表示系统中仅有低次版本号的共享库,但运行程序还是继续运行。有些采取更加保守策略的系统中,对于 这种系统中没有足够高的次版本号满足依赖关系的情况,程序将会被禁止运行,以防止出现意外情况。在采取第二种策略的系统中,如果系统中 只有低次版本号的共享库,那么这些程序就不能运行。我们可以把这个问题叫做次版本号交会问题
这种次版本号交会问题并没有因为SO-NAME 的存在而得到任何改善。 对于这个问题,现代的系统通过一种更加精巧的方式来解决,那就是符号版本机制。
- 基于符号的版本机制
Linux 下的Glibc 从版本2.1之后开始支持一种叫做基于符合的版本机制的方案。这个方案的基本思路是让每个导出和导入的符号都有一个相关联的版 本号,它的实际做法类似于名称修饰的方法。
当我们将libfoo.so.1.2升级至1.3时,仍然 保持 libfoo.so.1 这个 SO-NAME, 但是给在1.3这个新版中添加的那些全局符号打上一个标 记,比如“VERS 1.3”。那么,如果一个共享库每一次次版本号升级,我们都能给那些在新 的次版本号中添加的全局符号打上相应的标记,就可以清楚地看到共享库中的每个符号都拥 有相应的标签,比如“VERS 1.1”、“VERS 1.2”、“VERS 1.3”、“VERS 1.4”。
- Solaris 中的符号版本机制
Solaris 的ld链接器为共享库新增了版本机制和范围机制
版本机制的想法很简单,也就是定义一些符号的集合,这些集合本身都有名字,比如叫 “VERS 1.1”、“VERS 1.2”等,每个集合都包含一些指定的符号,除了可以拥有符号以外, 一个集合还可以包含另外一个集合,比如 “VERS 1.2”可以包含集合“VERS 1.1”。
在 Solaris 中,程序员可 以在链接共享库时编写一种叫做符号版本脚本的文件。链接器在链接时根据符号版本脚本中指定的关系来产 生共享库,并且设置符号的集合与它们之间的关系。
当共享库的符号都有了版本集合之后, 一个最明显的效果就是,当我们在构建(编译和 链接)应用程序的时候,链接器可以在程序的最终输出文件中记录下它所用到的版本符号集 合。
- GCC 对 Solaris 符号版本机制的扩展
GCC 还允许使用一个叫做“.symver”的汇编宏指令来指定符号的版本,这个汇编宏指令可以被用在GAS 汇编中,也可以在GCC的C/C++源代码中以嵌入汇编指令的模式使用。
asm(".symver add,addeVERS_1.1");
- Linux系统中符号版本机制实践
在 Linux下,当我们使用ld 链接一个共享库时,可以使用“-version-script”参数;如 果使用GCC, 则可以使用“-Xlinker”参数加“-version-script", 相当于把“-version-script” 传递给ld链接器。如编译源代码为“lib.c”, 符号版本脚本文件为"lib.ver":
gcc -shared -fpIC lib.c -Xlinker --version-script lib.ver -o lib.so
共享库系统路径
目前大多数包括 Linux在内的开源操作系统都遵守一个叫做 FHS的标准,这个标准规定了一个系统中的系统文件应该如何存放,包括各个目录的结构、组织和作用,这有利于促进各个开源操作系统之间的兼容性。
FHS 规定, 一个系统中主要有3个存放共享库的位置,它们分别如下:
- /ib,这个位置主要存放系统最关键和基础的共享库,比如动态链接器、 C 语言运行库、 数学库等
- /usr/lib,这个目录下主要保存的是一些非系统运行时所需要的关键性的共享库,主要是 一些开发时用到的共享库
- /usr/local/lib, 这个目录用来放置一些跟操作系统本身并不十分相关的库,主要是一些 第三方的应用程序的库
共享库查找过程
动态链接的ELF可执行文件在启动时同时会启动动态链接器。在Linux 系统中,动态链接器是/lib/ld-linux.so.X(X是版本号)。任何一个动态链接的模块所依赖的模块路径保存在“.dynamic” 段里面,由DT_NEED类型的项表示,如果DT_NEED里面保存的是绝对路径,那么动态链接器就按照这个路径去查找;如果DT_NEED里面保存的是相对路径,那么动态链接器会在/ib、/usr/lib 和由/etc/ld.so.conf 配置文件指定 的目录中查找共享库。
ld.so.conf 是一个文本配置文件,它可能包含其他的配置文件,这些配置文件中存放着 目录信息。
/usr/local/lib
/lib/i486-linux-gnu
/usr/lib/i486-linux-gnu
Linux 系统中都有一个叫做 ldconfig的程序,这个程序的作用是为共享库目录下的各个共享 库创建、删除或更新相应的SO-NAME (即相应的符号链接),这样每个共享库的 SO-NAME就能够指向正确的共享库文件;并且这个程序还会将这些SO-NAME收集起来,集中存放到letc/ld.so.cache 文件里面,并建立一个 SO-NAME的缓存。
环境变量
- LD_LIBRARY_PATH
Linux 系统提供了很多方法来改变动态链接器装载共享库路径的方法。改变共享库查找路径最简单的方法是使用LD_LIBRARY_PATH环境变量
- LD_PRELOAD
系统中另外还有一个环境变量叫做LD_PRELOAD,这个文件中我们可以指定预先装载 的一些共享库甚或是目标文件。在LD_PRELOAD里面指定的文件会在动态链接器按照固定 规则搜索共享库之前装载,它比LD_LIBRARY_PATH里面所指定的目录中的共享库还要优先。
- LD_DEBUG
另外还有一个非常有用的环境变量LD_DEBUG,这个变量可以打开动态链接器的调试功能,当我们设置这个变量时,动态链接器会在运行时打印出各种有用的信息,对于我们开发和调试共享库有很大的帮助。
LD_DEBUG=files ./HelloWorld.out
相关文章:
【链接装载与库】 Linux共享库的组织
Linux共享库的组织 由于动态链接的诸多优点,大量的程序开始使用动态链接机制,导致系统里面存在数量 极为庞大的共享对象。如果没有很好的方法将这些共享对象组织起来,整个系统中的共享对象文件则会散落在各个目录下,给长期的维护…...
大模型时代的机器人研究
机器人研究的一个长期目标是开发能够在物理上不同的环境中执行无数任务的“多面手”机器人。对语言和视觉领域而言,大量的原始数据可以训练这些模型,而且有虚拟应用程序可用于应用这些模型。与上述两个领域不同,机器人技术由于被锚定在物理世…...
devops步骤 -- jenkins安装
安装的docker-compose ##安装步骤参考: https://editor.csdn.net/md/?articleId133070011 编写docker-compose.yml version: 3 services: # 集合docker_jenkins:user: root # 为了避免一些…...
docker命令大全
1、查看Docker 容器占用的空间 docker ps -s2、查看所有容器 docker ps -a3、启动、关闭、重启一个已存在的容器 docker start <容器ID> docker stop <容器ID> docker restart <容器ID> 4、进入容器,退出终端的时候不会关闭container的ma…...
【EI会议征稿】第三届区块链、信息技术与智慧金融国际学术会议 (ICBIS2024)
第三届区块链、信息技术与智慧金融国际学术会议 (ICBIS2024) The 3rd International Academic Conference on Blockchain, Information Technology and Smart Finance 第三届区块链、信息技术与智慧金融国际学术会议 (ICBIS2024) 将于2024年2月23-25日在马来西亚举行。本次会…...
算法岗面经
诸神缄默不语-个人CSDN博文目录 呃这个是我之前写的,理论上我应该搜集题目→做出解答这样的,但是我现在不再继续找工作了,所以感觉这些题目用不到了,我就直接把之前整理的这些资料发出来得了。 以后有缘分的话会继续补的…...
Vue 事件修饰符
Vue 事件修饰符 在 Vue 中,事件修饰符允许我们在处理 DOM 事件时添加一些特殊的修饰符,以便更方便地控制事件的行为。以下是常用的 Vue 事件修饰符: .stop .stop 修饰符用于阻止事件冒泡,即停止事件在父元素之间的传播。 示例…...
FD-Align论文阅读
FD-Align: Feature Discrimination Alignment for Fine-tuning Pre-Trained Models in Few-Shot Learning(NeurIPS 2023) 主要工作是针对微调的和之前的prompt tuining,adapter系列对比 Motivation: 通过模型对虚假关联性的鲁棒…...
bug:Junit5报错,@SpringBootTest没有运行
1、首先解决Junit5报错 java.lang.NoClassDefFoundError: org/junit/platform/launcher/core/LauncherFactory 添加依赖 implementation org.junit.platform:junit-platform-launcher:1.8.2java.lang.IllegalArgumentException: Error: test loader org.eclipse.jdt.internal.…...
Clickhouse学习笔记(4)—— Clickhouse SQL
insert insert操作和mysql一致 标准语法:insert into [table_name] values(…),(….)从表到表的插入:insert into [table_name] select a,b,c from [table_name_2] update 和 delete ClickHouse 提供了 Delete 和 Update 的能力,这类操作…...
Centos, RockyLinux 常用软件安装汇总
一、基本指令: 命令作用clear清屏pwd显示当前路径cat / more显示文本文档uname -a查看当前版本hostnamectl查看当前版本cat /etc/redhat-release查看当前版本free查看剩余内存df -h[查看磁盘剩余空间]du -sh 查看文件夹名"dir"占用的空间lsof -i:8080查看…...
Lua更多语法与使用
文章目录 目的错误处理元表和元方法垃圾回收协程模块面向对象总结 目的 在前一篇文章: 《Lua入门使用与基础语法》 中介绍了一些基础的内容。这里将继续介绍Lua一些更多的内容。 同样的本文参考自官方手册: https://www.lua.org/manual/ 错误处理 下…...
探秘亚马逊云科技海外服务器 | 解析跨境云计算的前沿技术与应用
目录 一、什么是海外服务器 二、不同主流海外云服务器对比 三、海外服务器的创建(亚马逊为例) 四、个人总结 一、什么是海外服务器 亚马逊云科技海外服务器:指的是部署在世界各地的亚马逊数据中心中的服务器设备。这些服务器提供了计算、存储、数据库、网络等各…...
UnityAI——动物迁徙中的跟随实现实例
大家好,我是七七,今天来给大家介绍的是Unity中用操控行为实现的跟随领队行为。 看本文若是想了解和实现,只看本文即可,若是想彻底弄透,建议从七七的游戏AI专栏开始看。 废话不多说,先上视频: …...
堆的应用-----Top k 问题
目录 前言 Topk问题 1.问题描述 2.解决方法 3.代码实现(C/C) 前言 在人工智能算法岗位的面试中,TopK是问得最多的几个问题之一: 到底有几种方法? 这些方案里蕴含的优化思路究竟是怎么样的? 为啥T…...
11月14日星期二今日早报简报微语报早读
11月14日星期二,农历十月初二,早报微语早读。 1、江西南城县:限时发放购房补贴政策,三孩家庭每平方米最高补贴500元; 2、2023年中国内地电影市场累计票房突破500亿元; 3、市场监管总局:在全国…...
Spark读取excel文件
文章目录 一、excel数据源转成csv二、Spark读取csv文件(一)启动spark-shell(二)读取csv生成df(三)查看df内容一、excel数据源转成csv 集群bigdata - ubuntu: 192.168.191.19master(bigdata1) - centos: 192.168.23.78 slave1(bigdata2) - centos: 192.168.23.79 slave2(b…...
LLM大语言模型(典型ChatGPT)入门指南
文章目录 一、基础概念学习篇1.1 langchain视频学习笔记1.2 Finetune LLM视频学习笔记 二、实践篇2.1 预先下载模型:2.2 LangChain2.3 Colab demo2.3 text-generation-webui 三、国内项目实践langchain-chatchat 一、基础概念学习篇 1.1 langchain视频学习笔记 lan…...
Spring IOC - Bean的生命周期之实例化
在Spring启动流程文章中讲到,容器的初始化是从refresh方法开始的,其在初始化的过程中会调用finishBeanFactoryInitialization方法。 而在该方法中则会调用DefaultListableBeanFactory#preInstantiateSingletons方法,该方法的核心作用是初始化…...
前端 BUG 总结
文章目录 CSS 样式1、Chrome 89 版本期不再支持 /deep/,请勿使用嵌套 /deep/2、圆角按钮 button 点击后出现矩形框线3、怪异模式4、border 1 像素在手机上显示问题5、文本溢出问题 JavaScript 脚本1、移动端点击穿透2、使用parseInt时必须补全第二个参数 radix3、有…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
