装载的简单介绍

本文详细解释了程序执行时的数据装载过程,包括静态与动态装载的区别,覆盖装入与页映射的不同,以及操作系统如何创建虚拟地址空间并映射可执行文件。此外,还对比了Section与Segment的区别。
部署运行你感兴趣的模型镜像

一、什么是装载?

程序执行时所需要的指令与数据必须都在内存中才能正常运行,这些需要的数据装入的过程即为装载

装载一般分为两种:
1、静态装入

将所需要的指令和数据全部装入内存中,这时最简单的方法

2、动态装入

利用程序运行时的局部性原理,将程序最常用的部分留在内存中,不太常用的数据放于磁盘中

对于上面的第一种情况,如果可执行文件太大,程序所需要的内存数量大于物理内存的数量时,第一种装载的方式明显不行,于是第二种动态装入的方法才是最好的选择。

对于动态装入的方式,也存在两种:
覆盖装入:

让程序员将程序分割成若干块,编写一个辅助代码来管理这些模块。

页映射:

将内存和所有磁盘中的数据和指令按照页为单位划分,之后装载和操作的单位就是页。

其中覆盖装入的方式已经被淘汰,是没有发明虚拟存储前的动态装载方式。其存在着一些缺陷,存在某些模块间的地址冲突,从而导致无法同时使用冲突的模块。
这里写图片描述
可以看到,图中A、B两个模块之间的地址重合,于是使用A模块后再使用B模块的话,必然会将A模块的部分覆盖掉,这只是一个比较简单的例子,真正的程序中会存在许多模块,会更加复杂,同时需要程序员来编写头部的Overlay Manager(覆盖管理器)来管理模块的驻留或是替换,因此存在缺陷。

页映射的装入方式是虚拟存储机制的一部分,随着虚拟存储的发明而诞生。
这里写图片描述
如图中所示,将ELF文件按页划分,于是装入的时候只需要按页为单位装入,即可实现程序的执行。
不过这种方法也有个很明显的问题,如果程序需要访问P4,那么装载管理器必须做出抉择,必须放弃正在使用的4个内存页中的一个来装载P4,于是选择哪个页就成了问题,有着很多的算法,包括FIFO(先进先出算法)、LUR(最少使用算法)等等。其实这里的装载管理器就是现代的操作系统的存储管理器。

二、从操作系统角度看可执行文件装载

上面简单介绍了装载的概念,接下来站在操作系统的角度来看一个可执行文件的装载和执行过程。

从操作系统来看,每个进程最关键的特征就是其有着独立的虚拟地址空间。
通常,一个程序被执行的同时伴随着一个新的进程被创建,即创建一个进程,然后装载相应可执行文件,此种情况下总共需要完成三件事:
1、创建一个独立的虚拟地址空间;

一个虚拟空间由一组页映射函数将虚拟空间的各个页映射到相应的物理空间,于是创建一个虚拟空间实际上就是创建映射函数所需要的相应数据结构,实际上就是建立一个页目录,甚至页映射关系都会等到后面发现页错误的时候再进行设置

2、读取可执行文件头,建立虚拟空间与可执行文件的映射关系;

当程序执行发生页错误时,操作系统从屋里内存中分配一个物理页,然后将所缺的那一页从磁盘中读入内存中,在设置却也的虚拟页与物理页的映射关系,然后程序得以执行。
但是存在一个很明显的问题,发生页错误后,系统如何知道该读入的那一页在哪里?或者说在可执行文件中的哪个位置?因此这一步即让操作系统发生页错误后能够知晓缺少的那一页在可执行文件的哪个位置,于是才能将其读入内存中,继而建立虚拟页与物理页的映射关系,从而执行程序。

3、将CPU指令寄存器设置为可执行文件的入口地址,启动运行。

让CPU下一步从可执行文件的入口开始执行可执行文件,程序成功运行。但是这一步中会牵扯到内核堆栈、用户堆栈等的切换,所以并不像看上去这么简单。

刚刚的三步过程后CPU开始从程序的入口地址开始执行,发现第一个页是空页,于是发生了页错误,操作系统通过缺页、请页机制将所需的页从磁盘中装入内存中,于是不断发生页错误,不断将页装入内存中,程序得以执行。当出现进程需要的内存超过可用内存数时,操作系统进行组织和分配物理内存,将分配配给进程的物理内存暂时回收并再次进行分配。

三、Section与Segment的区别

我们都知道一个可执行文件中往往包含了很多段,包括代码段(.text)、数据段(.data)等,实际上这些段我们一般称为Section。
这里写图片描述
上面就是一个简单程序的Seciton的分布,并没有显示完全,不过总计有31个Section,代码段、数据段以及一些我们不知道用处的段等等都在其中

ELF文件被映射时,是以系统的页长度作为单位的,每个Section在映射时长度都应该是系统页长度的整数倍,如果不是的话,那么向上补足,即不到一页也分配一页。
想象一下,上面那个ELF文件中有着31个Section,我们无法保证每个Section的长度都刚好是系统页长度的整数倍,那么31个Section的映射就意味着要浪费很多内存,为了节省内存,于是产生了Segment这个概念。
这里写图片描述
上面是相同ELF文件的Segment信息,其中Segment只有6个,并且类型为LOAD即需要装载到内存中的Segment只有两个,这样相比于映射31个不同的Section来说节省了许多内存

那么Segment与Section的区别是什么?
其实从上图中能够看到答案,Segment即多个Section的集合。那么多的Section,如果按照权限来归类也只有三类,即:
1、权限为可读可执行,以代码段为代表;
2、权限为可读可写,以数据段及BSS段为代表;
3、权限为只读的段,以只读数据段为代表。
既然分类了,那么就简单了,将相同权限的Section合并为一个Segment,这样就能够节省大量的内存。从上图中可以看到,对于LOAD类型的两个Segment,第一个是由.init、.text等Section合并而成,权限为RE(可读可执行),第二个是由.data、.bss等Section合并而成,权限为RW(可读可写)。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### PWM基本原理及应用简介 #### ### 脉宽调制(PWM)概述 脉宽调制(Pulse Width Modulation, PWM)是一种利用数字信号来表示模拟信号的技术。它的核心思想是通过对一系列固定频率的方波信号的占空比进行调节,从而实现对输出平均电压或功率的有效控制[^1]。 在一个典型的PWM信号中,有两个主要参数决定其特性: - **占空比**:定义为高电平时间与整个周期时间的比例。例如,如果一个周期内的高电平时间为总周期的一半,则该信号的占空比为50%。 - **频率**:即每秒内完成的完整周期数量。较高的频率有助于使负载感知到更加平稳的变化效果[^2]。 这种技术能够高效地将直流电源转化为可变幅值的等效交流源,适用于多种场景如速度控制、灯光调节等领域[^3]。 #### ### 工作机制说明 当提到如何通过PWM生成近似连续变化的电压水平时,这实际上是借助快速切换开关器件之间的时间分配达成的目标。假设系统供电电压为3伏特,在理想情况下,如果我们让这个输出端保持三分之一时间段处于开启(即提供全压),其余部分关闭的话,那么从宏观角度来看,连接在此处的小型设备会感受到大约相当于一伏特的有效输入[^2]。 此外值得注意的是,在实际运用当中,为了让人类眼睛无法察觉到任何波动现象发生——特别是针对视觉反馈类装置而言—我们往往选取足够高的工作频率使得肉眼难以分辨单独帧间的差异;与此同时调整相应的Duty Cycle百分比率即可轻松改变发光二极管(LEDs)之类组件发出光线强度大小,进而营造出柔和渐变式的照明体验,也就是常说的“呼吸灯”效应[^3]。 ```c // 示例代码:STM32配置基础定时器产生PWM信号 #include "stm32f1xx_hal.h" TIM_HandleTypeDef htim; void MX_TIM_Init(void){ __HAL_RCC_TIM2_CLK_ENABLE(); TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim.Instance = TIM2; htim.Init.Prescaler = 71; // 设置预分频器值 htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 999; // 自动重装载值设定 HAL_TIM_PWM_Init(&htim); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 初始占空比设置 HAL_TIM_PWM_ConfigChannel(&htim,&sConfigOC,TIM_CHANNEL_1); } int main(){ HAL_Init(); MX_TIM_Init(); HAL_TIM_PWM_Start(&htim,TIM_CHANNEL_1); while (1){} } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值