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脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

详解Linux中常见环境变量的特点与设置

《详解Linux中常见环境变量的特点与设置》环境变量是操作系统和用户设置的一些动态键值对,为运行的程序提供配置信息,理解环境变量对于系统管理、软件开发都很重要,下面小编就为大家详细介绍一下吧... 目录前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

Linux中修改Apache HTTP Server(httpd)默认端口的完整指南

《Linux中修改ApacheHTTPServer(httpd)默认端口的完整指南》ApacheHTTPServer(简称httpd)是Linux系统中最常用的Web服务器之一,本文将详细介绍如何... 目录一、修改 httpd 默认端口的步骤1. 查找 httpd 配置文件路径2. 编辑配置文件3. 保存

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

Linux使用scp进行远程目录文件复制的详细步骤和示例

《Linux使用scp进行远程目录文件复制的详细步骤和示例》在Linux系统中,scp(安全复制协议)是一个使用SSH(安全外壳协议)进行文件和目录安全传输的命令,它允许在远程主机之间复制文件和目录,... 目录1. 什么是scp?2. 语法3. 示例示例 1: 复制本地目录到远程主机示例 2: 复制远程主

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可