【Linux】程序地址空间之动态库的加载

news2024/12/26 10:37:09

我们先进行一个整体轮廓的了解,随后在深入理解细节。
在动态库加载之前还要说一下程序的加载,因为理解了程序的加载对动态库会有更深的理解。

轮廓:

首先,不管是程序还是动态库刚开始都是在磁盘中的,想要执行对应的可执行程序或者编译都需要一个指定的路径才可以找到。他就像我们现实生活中的地址,当然这些对我们程序地址空间的影响不大,主要是因为路径太重要了,进行一下强调。

在这里插入图片描述
从图中可以比较清晰的看到动态库加载的简略行为,随后在执行到库函数的地方时跳转到共享区,执行完在跳转回来即可。
可是这个库只会被一个进程使用吗?

我们看到一个动态库可能会被多个进程同时使用
在这里插入图片描述
所以当我们由另外的进程时,不需要重新加载动态库了,只要用现成的,直接使用页表映射即可。因为他能被多个库同时使用,所以也叫共享库!

程序的加载:

说在前边,程序的加载需要说一大堆预备的知识,最后才能进行串起来。

我们谈这个之前先想一个问题:我们编译好的程序的二进制代码中会有“地址”吗?
我们验证一下:
在这里插入图片描述
对此文件进行一下objdump -S code(反汇编)
在这里插入图片描述
可以看到其中就已经存在一种类似地址的东西了。

同时我们进行size可以看到这个可执行程序已经分好了各种区域,类似我们mm_struct中的地址空间划分。
在这里插入图片描述
那我们在程序中定义的变量名也理所当然的变为了地址。

至此我们知道了可执行程序中存在地址与空间划分了

linux中生成的可执行程序格式叫做ELF。
这个二进制可执行程序有自己固定的格式,elf可执行程序的头部有着自己的属性。
另外我们的文件经过编译后,有很多的汇编语句,我们已经见到过了,这是什么地址呢?是如何进行编址?

先回答第二个问题
我们在编址时一般有两种:其一是相对编址;其二是绝对编址。

相对编址时,使用起始地址加上对应的偏移量
在这里插入图片描述
绝对编址:
在这里插入图片描述
绝对编址就是我们本身的方式,也叫做平坦模式,所以整体是线性增长的。
同时我们也可以认为这其实就是虚拟地址

所以我们的汇编程序中就已经存在虚拟地址了。

此时我们还需要设计一个东西叫做加载器:
在这里插入图片描述
我们会先把加载器的库加载到内存中,执行库中的方法将可执行程序拷贝到内存,加载器对可执行程序的头部进行解释。可以得到main函数的地址。

所以 ELF + 加载器 = 各个区域中的起始位置与结束位置 + main函数地址。

现在我们基本就将预备知识铺垫的差不多了。

可以进入主线了。
我们常说进程 = 内核数据结构+代码和数据。
那么当我们执行一个程序时是先创建内核数据结构还是先将文件加载到内存中呢?
我们这样想:当你被学校录取后,你是开学到了学校才是这个学校的学生还是当志愿填报结束你得到了被录取的信息才是呢?
答案是显然的,当你收到了录取通知就已经是学校的学生了。

那我们进程也是先有内核数据结构在加载程序。
那我们就要开始创建内核数据结构了。
在这里插入图片描述
我们的mm_struct是一个对象,其中有成员变量,变量的初始值是什么?
我们的可执行程序中就已经提供了对应的分配好了各个地址,就可以去填充了。

所以虚拟地址空间这个概念不是OS独有的,是由OS+编译器+加载器一起构成的。

我们不会提到一个没有用的事物,对于main函数的地址我们该怎么用呢?
我们的CPU中有一个PC指针,他保存的是当前执行指令的下一条虚拟地址。
在最开始的时候就是main的地址。这是很关键的一环。

所以我们要开始加载程序到内存咯。
在这里插入图片描述

尽管我们的程序中有自己的虚拟地址,但是加载到物理内存中仍然会有属于自己的物理地址。

那我们现在就需要将mm_struct与内存进行连接起来,那就是页表!
在这里插入图片描述
我们现在开始运行!
根据PC指针的值去页表中映射对应的物理地址,拿到指令去执行,循环往复就执行起来啦!

这就是程序加载的过程。
我们只要分为两个阶段看就会好一点

  1. 内核数据结构的创建
  2. 程序的加载

还有额外的预备知识~

动态库的加载:

我们的动态库编译好之后和可执行程序基本是一样的,也有自己的地址。
,只不过没有main的地址罢了。
在这里插入图片描述

先来画一个图。
假设我们的代码中有一个调用库中的代码Add。
在这里插入图片描述

当我们执行到Add时,此时我们的动态库还没加载,那么当然就需要将动态库也加载到内存,同时映射到虚拟地址空间。
在这里插入图片描述

这里有一个细节,我们程序加载到内存映射到地址空间时,只有一个虚拟地址,直接就是二进制程序提供的。可是此时我们的虚拟地址有两份,一个是库中我们要调的函数的地址,一个是mm_struct中动态库的地址。

实际上库中的函数地址就是库函数地址为0的偏移量,当想要访问到库函数时,我们就需要知道他的地址,他的地址就是两者的相加:0x5555+0x1111=0x6666。
所以有了地址我们就可以动态库的函数了,也就是跳转到共享区,执行完毕再跳回来。

所以这个地址被映射到虚拟地址空间的那个位置重要吗?
并不重要,所以制作动态库时需要-fPIC,叫做与地址无关码!


可是我们加动态库时怎么知道有没有被加载?
同时动态库还要存在多份。

所以就需要管理:所以就要有对应的描述结构体与组织他的数据结构(比如链表)。
当我们加载时先遍历一遍观察是否已经加载,有的话直接映射,没有的话就加载…

到此完毕~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1835903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

隧道代理是什么?怎么运作的?

隧道代理作为网络代理的一种形式,已经在现代互联网世界中扮演着重要的角色。无论是保护隐私、访问受限网站还是实现网络流量的安全传输,隧道代理都发挥着重要作用。在本文中,我们将深入探讨隧道代理的概念、运作方式以及在不同场景中的应用。…

ClickHouse 高性能的列式数据库管理系统

ClickHouse是一个高性能的列式数据库管理系统(DBMS),主要用于在线分析处理查询(OLAP)。以下是对ClickHouse的详细介绍: 基本信息: 来源:由俄罗斯的Yandex公司于2016年开源。全称&…

在向量数据库中存储多模态数据,通过文字搜索图片

在向量数据中存储多模态数据,通过文字搜索图片,Chroma 支持文字和图片,通过 OpenClip 模型对文字以及图片做 Embedding。本文通过 Chroma 实现一个文字搜索图片的功能。 OpenClip CLIP(Contrastive Language-Image Pretraining&…

Eigen中 Row-Major 和 Column-Major 存储顺序的区别

Eigen中 Row-Major 和 Column-Major 存储顺序的区别 flyfish Eigen::RowMajor 是 Eigen 库中用于指定矩阵存储顺序的一种选项 理解 Row-Major 和 Column-Major 存储顺序的区别,绘制一个单一的图来显示内存中的元素访问顺序,在图中用箭头表示访问顺序. import nu…

【无重复字符的最长子串】

无重复字符的最长字串 一、题目二、解决方法1.暴力解法2.滑动窗口哈希 三、总结1.es6 new set()的用法添加元素add()删除元素delete()判断元素是否存在has 2.滑动窗口和双指针的联系和特点 一、题目 二、解决方法 1.暴力解法 解题思路:使用两层循环逐个生成子字符串…

Ardupilot开源代码之ExpressLRS性能实测方法

Ardupilot开源代码之ExpressLRS性能实测方法 1. 源由2. 测试效果3. 测试配置4. 总结5. 参考资料6. 补充 1. 源由 之前一直在讨论ExpressLRS性能的问题,有理论、模拟、实测。 始终缺乏完整的同一次测试的测试数据集,本章节将介绍如何在Ardupilot上进行获…

聆思CSK6大模型+AI交互多模态开源SDK介绍

视觉语音大模型 AI 开发套件( CSK6-MIX )是围绕 CSK6011A 芯片设计的具备丰富语音图像功能与硬件外设的开发板,采用具备丰富组件生态的 Zephyr RTOS作为操作系统,官方提供了十几种开源SDK,包含大模型语音交互、大模型拍照识图、文生图、人脸识…

spark常见问题

写文章只是为了学习总结或者工作内容备忘,不保证及时性和准确性,看到的权当个参考哈! 1. 执行Broadcast大表时,等待超时异常(awaitResult) 现象:org.apache.spark.SparkException: Exception…

设置角色运动的动画

(1) 打开Assets-UnityTechnologies-Animation-Animators,Create-Animation-Controller,命名为JohnLemon (2) 打开JohnLemon,出现下图 (3) 依次将Assets-UnityTechnologies-Animation-Animation中的JohnIdle和JohnWalk拖放到Base Layer窗口中 (4) 右击Idl…

整合JavaSSM框架【超详细】

在整合SSM之前我们首先要知道SSM框架指的是哪些框架? Java的SSM指的是Spring、Spring MVC、MyBatis这三个框架 Spring框架 什么是Spring? Spring是一个支持快速开发Java EE应用程序的框架。它提供了一系列底层容器和基础设施,并可以和大量常…

win11右键小工具

开头要说的 在日常使用场景中,大家如果用的是新的笔记本电脑,应该都是安装的win11系统, 当然win11系统是最被诟病的, 因为有很多人觉得很难操作, 就比如一个小小的解压操作, 在win7和win10上&#xff…

基于DDD的编码实践

分层设计 领域驱动设计(Domain-driven design, DDD) 作为一种复杂软件系统的应对方案,在设计和编码提供了一种新的解决方式,即领域驱动,要求程序员在设计和编码时从领域专家的角度出发来实现架构/代码,做到…

随机产生一些江河上的坐标数据

不久前收到一个需求,说要随机创建约一百个某段江河上的坐标点,用于做一些数据呈现。 我首先是想到用AI直接给我一点数据,没想到给出来的坐标,有许多都落在陆地上,根本不符合我的要求。后来结合AI给出的建议&#xff0…

爬抖音直播间观众数据

打开抖音,稍微看了下买房直播间,突然很好奇是那些用户在观看,想拿下这些用户数据,再通过用户等级、在线观看时长排序,筛选出优质客户。 普及一下抖音用户等级: 抖音用户的提升与用户在直播间消费的金额直接…

打造基于大模型的AI产品

我要飞往印度进行短暂旅行,因此花了一个小时的时间处理在线签证申请流程。完成后,由于我现在知道涉及的内容,我向 ChatGPT 4o 询问了相关问题。这些观点中的大多数都是部分或完全错误的。 NSDT工具推荐: Three.js AI纹理开发包 - …

Linux C编译器从零开发三

AST语法树 BNF抽象 expr equality equality relational ("" relational | "!" relational)* relational add ("<" add | "<" add | ">" add | ">" add)* add mul ("" …

苹果电脑下载vite包错

苹果电脑下载vite包错/Users/lili/.npm/_cacache/index-v5/c5/50/b451703d03b3802b9ee6b7ff2b0bde4de7f26830eb52c904d6911c137cf8包错解决方式 解决方式&#xff1a;sudo chown -R 501:20 "/Users/wangxin/.npm"

2024/6/18(RBAC,查询用户权限,细粒度授权,选课,支付宝生成二维码支付,支付结果查询需要内网穿透)

黑马程序员【学成在线项目】,P141 测试沙箱支付宝_黑马学成在线支付宝沙箱-CSDN博客 需要内网穿透

甘特图如何画以及具体实例详解

甘特图如何画以及具体实例详解 甘特图是一种常见的项目管理工具又称为横道图、条状图(Bar chart)。是每一位项目经理和PMO必须掌握的项目管理工具。甘特图通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。但是多项目经理和PMO虽然考了各种证…

OSPF开销、协议优先级、定时器(华为)

#交换设备 OSPF开销值 如果没有定义OSPF接口的开销值&#xff0c;OSPF会根据该接口的带宽自动计算其开销值。 计算公式&#xff1a; 接口开销 带宽参考值 / 接口带宽 &#xff08;取整数部分&#xff0c;结果小于1时取1&#xff09;通过改变带宽参考值可以间接改变接口的开…