当前位置: 首页 > news >正文

动态库与ELF加载

目录

动态库

ELF格式

ELF和后缀的区别

什么是目标文件

ELF文件中的地址--虚拟地址

动静态库和可执行文件

动态库ELF加载

为什么编译时静态库需要指定库?而运行时不需要指定库的,但是动态库需要呢?

总结:


动态库

动态库制作需要的.o文件需要使用选项fPIC

g++ -c -fPIC test.cc -o test

制作成动态库需要的是指令是g++ -shared -o libmylib.so test.o

运行时查找动态库

动态库链接分为编译和运行

gcc/g++的时候也是链接了的,只不过没有拷贝到可执行程序中,而是建立联系,等待可执行程序执行时才会再次查找动态库中的具体内容

这也是动态库和静态库的区别,静态库在链接的时候会把代码拷贝到可执行程序中,这样的话其实静态库怎样变都不会影响可执行程序了,因为可执行程序中有备份;

但是动态库不是会将库的内容拷贝到可执行程序中而是运行时需要加载到内存中的,是实时加载的,所以动态库改变也会影响到可执行程序

运行时查找是默认系统路径中查找的?

为什么是在默认系统路径,为什么是默认的,因为在环境变量中;

LD_LABRARY_PATH;

对环境变量赋值 export LD_LABRARY_PATH=绝对路径

打印环境变量---> echo $LD_LABRARY_PATH

ELF格式

ELF 是可执行与可链接格式,是一种通用的目标文件格式。它能让程序在不同系统上方便地编译、链接和运行。ELF 文件里有代码段、数据段这些不同的段,还有符号表、重定位信息等。代码段存程序指令,数据段放程序用到的数据。符号表记录函数、变量等的信息,重定位信息帮链接器确定地址。它的结构清晰,能很好地支持程序的加载和执行呢。

ELF和后缀的区别

ELF 主要是一种文件格式规范,跟文件后缀没必然联系。它定义了目标文件、可执行文件等的结构和内容组织方式。像.o 文件、可执行文件,还有共享库等都可以是 ELF 格式。虽然常见的 C 语言源文件有.c、.cpp 等后缀,但经过编译链接生成的目标文件和可执行程序如果符合 ELF 规范,那就是 ELF 格式的文件啦,跟源文件后缀没关系哦。

什么是目标文件

编译过程中的.o文件和可执行程序文件都是目标文件。

可执行程序其实就是把多个.o文件经过链接整合起来的,本质上还是多个.o文件,内容格式就是ELF格式

ELF文件中的地址--虚拟地址

经过编译形成ELF格式的目标文件后,这个时候其实就是对进程的虚拟地址进行了规划,虽然还没有产生进程,也没有被分配对应的物理空间,这算是一个“蓝图”;

然后我们执行可执行程序的时候,进程被创建操作系统会分配给该进程一个大块的物理内存空间,然后一遍执行一遍维护页表,建立虚拟地址和物理地址的映射关系,然后再对应的物理内存上加载数据;

在程序执行完毕后,就会释放掉物理内存和页表(这都是在物理空间中的),如果没有对其他文件操作,那么就没有什么数据保留下来,可执行程序也会在内存中释放掉,但是磁盘上保留着文件,所以下次可以在使用

动静态库和可执行文件

动静态库本质就是对目标文件打包了,内部的各个目标文件没有建立联系,而可执行程序他是把目标文件建立了链接,其中的目标文件都是有联系的;但本质他们都是目标文件,二进制指令;

动态库ELF加载

通常情况下,加载动态库时,系统会先把整个库加载到内存,但并不会一次性把所有函数都加载到可执行程序中。只有当程序执行到需要调用动态库中某个函数的位置时,才会真正把这个函数的代码加载到可执行程序的地址空间里,这就是所谓的 “按需加载”。这样做可以有效节省内存资源,特别是对于那些包含很多函数,但程序只用到其中一部分的动态库来说,优势很明显。不过,不同的操作系统和动态链接器在具体实现上可能会有一些细微差别,但总体思路是类似的。

为什么编译时静态库需要指定库?而运行时不需要指定库的,但是动态库需要呢?

编译的过程是对语法检查,而不涉及内存逻辑上的检查,所以我们的代码中使用到了别的第三方库文件的时候,我们使用了对应文件中的函数和变量声明,在形成可执行文件的过程中其实就会对当前的文件进行语法检查,但是不会检查其他文件中的函数实现;


运行时已经生成了可执行程序,这个时候如果报错就是逻辑上的错误,只能针对源代码再次编译了;

而之所以静态库不需要再运行时指明库,那是因为在链接的过程中,其实已经把静态库的内容镶嵌到了可执行程序中;可执行程序执行中可以直接使用;

那为什么动态库就需要指明库路径呢?

那是因为动态库并没有把内容放到可执行程序中,链接过程中,他只是和可执行程序建立了“羁绊”,可执行程序可以使用动态库内容,需要的时候就会加载到内存中,这个就是ELF动态加载,所以动态库实时使用,随用随拿的,如果动态发生更改,那么可执行程序就会收到影响;

总结:

所以链接时,需要的是库中的内容函数实现,动态库因为没有在可执行程序中,所以需要指定查找;

而编译时需要的是检查的库内容,也就是头文件,所以如果我们只是为了得到.o目标文件那么是不需要指明动静态库路径的;

我们平时是直接从源文件直接生成可执行程序,所以需要头文件和动静态库同时使用;如果是动态库那么就还需要注意运行时查找动态库路径;---环境变量配置

http://www.xdnf.cn/news/268741.html

相关文章:

  • LabVIEW三轴电机控制
  • 如何实现一个虚拟dom
  • 5月3日星期六今日早报简报微语报早读
  • Vue3学习笔记2——路由守卫
  • 修改或禁用Cursor的全局搜索默认快捷键
  • CSS 优化与渲染性能调研
  • Java变量简介
  • 【2025软考高级架构师】——软件专利(12)
  • 【STM32】定时器输出比较模式
  • C# 方法(控制流和方法调用)
  • 论面向方面编程及其应用
  • 失败复盘:2077首发灾难的原因
  • Python基本语法(函数partial)
  • Python函数参数机制深度解析与最佳实践
  • Leetcode刷题记录28——缺失的第一个正数
  • 山东大学离散数学第十章习题解析
  • 测试基础笔记第十八天
  • PyTorch_创建01张量
  • 【深度学习基础】:VGG实战篇(图像风格迁移)
  • [Windows] Kazumi番剧采集v1.6.9:支持自定义规则+在线观看+弹幕,跨平台下载
  • ecs网站备份,ecs网站备份的方法
  • 基于YOLOv8的人流量识别分析系统
  • 普通 html 项目引入 tailwindcss
  • 【算法专题九】链表
  • Socket 编程 UDP
  • C++继承基础总结
  • GESP2024年6月认证C++八级( 第三部分编程题(2)空间跳跃)
  • VFS Global 携手 SAP 推动数字化转型
  • Three.js支持模型格式区别、建议
  • <property name=“userDao“ ref=“userDaoBean“/> 这两个的作用和语法