Linux:动态库加载、编址

2024-04-12 03:04
文章标签 动态 linux 加载 编址

本文主要是介绍Linux:动态库加载、编址,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、库的概念

二、动静态库的加载

2.1绝对编址与相对编址

2.1一般程序的加载

三、动态库的加载


一、库的概念

库默认就是一个磁盘级文件,所以在执行代码时,库和可执行程序都会被加载到内存中,从原理上,库函数的调用依旧是在进程的地址空间中进行的。动态库/共享库只需要加载一份,然后通过页表映射到不同的进程地址空间中,所以就可以做到让多个进程使用同一份代码。

而库的加载由操作系统来决定,并且对已经加载的库进行管理,也就是先描述再组织。

和管理进程时类似,对加载进来的库的管理也可以转变为对链表的增删查改。

每个可执行程序都是有自己的格式信息的,即使可执行程序没有加载到内存中,我们的可执行程序中就有地址 ,可执行程序在没有被加载之前,也已经基本按照类别(比如权限,访问属性等)已经将可执行程序划分为各个区域了。

我们在创建一个进程,执行一个进程时,我们是如何对进程地址空间进行划分处理,去加载代码和数据的呢?操作系统是怎么知道该开辟多大空间怎么划分的呢?

我们进程地址空间里面的很多地址数据,是从要执行的可执行程序中来的。

二、动静态库的加载

2.1绝对编址与相对编址

可执行代码与数据如果从上到下从前到后进行连续的编址,这种方式称为绝对编址,也就是所谓的平坦模式。

如果我们将数据区与代码区分开,代码区从0开始,数据区从0开始,使用这种偏移量的方式,我们一般叫做相对地址也叫逻辑地址。

 虚拟地址空间不仅仅是操作系统要遵守,编译器编译程序时也需要遵守。

2.1一般程序的加载

即使没有加载程序本身也有地址,任何一个函数经过编制就没有变量名了,每个函数都是有入口的,所以程序形成可执行程序存到磁盘中加载到内存之前,本身就有编址了,每个程序还要ELF格式的表头,表头中也会记录类似于入口地址,整个可执行程序的区域划分,和各个区域的起始地址。

最终这个东西才是一个完整的可执行程序,而它的编址方式也采用绝对编址,从上到下挨着进行编,当然我们也可以将其看作其在磁盘中的逻辑地址也就是0+0X0000。

要将可执行程序加载到内存首先要创建一个进程,首先创建task_struct即PCB进程控制块,然后加载进程地址空间,而进程地址空间mm_strucr是从可执行程序的ELF表头来加载的。所以不同的程序就有不同的正文段,已初始化未初始化的范围大小。

而cpu中存在一个寄存器CR3保存页表的起始地址,而进程地址空间可以用可执行程序本身来进行初始化,所以可执行程序的大小也决定了进程地址空间的大小,然后将可执行程序代码加载到物理内存中,此时加载到物理内存的地址就是所谓的真实物理地址,而此时可执行程序内部的绝对编址就直接作为虚拟地址和物理地址进行映射建立页表。

而cpu寄存器中有个pc指针,也叫程序计数器,保存正在执行的下一条指令的地址,将ELF中存储的入口地址加载到pc指针,cpu中还有指令寄存器,经过MMU加页表将虚拟地址转换为物理地址,将指令读取然后去内存中查找执行。

所谓的地址空间本质是由操作系统+编译器+计算机体系结构(CPU)三者配合完成的。

所以逻辑地址和虚拟地址以及线性地址都是一个概念,物理地址则是在内存中的地址。

三、动态库的加载

 而可执行程序如何和库进行链接呢?

而库在磁盘中是按相对编制的方法来编址的,库有个起始地址,通过库的起始地址加上里面的各种函数指令所对应的偏移量来找到并执行该指令,而链接时只需要将调用的指令变成库的起始地点加上偏移量的方式存放在可执行程序中,并在前面包含头文件。

库加载到内存后,操作系统为了管理这个库,就会进行先描述再组织,会记录下来这个库被加载到了哪个位置。当cpu去执行和该库相关的指令时,系统只需要通过动态链接知道要执行哪个库,然后找到库的起始地址加上偏移量映射到共享区中库的虚拟地址,然后再通过页表找到库在内存中的位置,然后将指令加载到cpu去执行。

而库的地址在加载到进程地址空间时,一般是通过编址的地址加上偏移量形成一个地址然后得到进程地址空间中的绝对地址,这叫做地址加载时的动态重定向方式。

这篇关于Linux:动态库加载、编址的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/895927

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

Java导出Excel动态表头的示例详解

《Java导出Excel动态表头的示例详解》这篇文章主要为大家详细介绍了Java导出Excel动态表头的相关知识,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录前言一、效果展示二、代码实现1.固定头实体类2.动态头实现3.导出动态头前言本文只记录大致思路以及做法,代码不进

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程