动态库和静态库详解

库其实就是个文件

下面是文件后缀

静态库:.a(linux)   .lib(windows)

动态库:.so(linux) .dll(windows)

静态库的制作

ar   -rc   libmystdio.a   my_stdio.o   my_string.o

ar是归档工具,rc表示replace和create,ar跟tar有点像,把.o文件打包到一块,其他啥也不干

ar  -tv  libmystdio.a 

t: 列出静态库中的⽂件 ,v:详细信息,查看静态库

动态库的制作

libmystdio.so:my_stdio.o my_string.o
        gcc -o $@ $^ -shared
%.o:%.c
        gcc -fPIC -c $<
制作动态库的目标文件必须是源文件-fPIC编译成的,pic意思是位置无关编码,pic编译和普通的编译有什么区别呢?
正常的编译如果你调用一个函数,编出来的指令是call 临时地址,那pic编译呢,call pc+临时偏移量,这个偏移量是目标函数和pc之间的相对距离。因为动态库的加载位置是共享区,起始位置不固定,所以不能用绝对地址
生成动态库的过程其实就是把pic编译的目标文件给链接起来,要加-shared选项,表示不是链接出一个可执行文件而是动态库

 

库的使用

库这个文件的用处,就是和其他目标文件一起链接得到可执行程序
引⼊库的名称:去掉前缀 lib ,去掉后缀 .so , .a ,如: libc.so -> c
gcc main.c -I 头⽂件路径 -L 库⽂件路径 -lmymath
先编译main.c成目标文件,再和mymath库链接,得到最后的同名可执行文件main

ELF文件

那些文件是ELF文件?

.o目标文件

.exe可执行文件

.so动态库文件

核心转储文件

ELF文件的格式

ELF(ELF header)

程序头表 (Program header table)
节( Section
节头表 (Section header table)

1. 节头表(Section Header Table)​

  • 描述目标文件(.o)中的各个​​节(section)​​(如 .text.data.symtab 等),供​​静态链接器​​(ld)使用
  • 链接时,链接器会合并不同目标文件中的​​同名节​​(如将所有 .text 合并到代码段)成段。
  • ​​动态库/可执行文件可以没有节头表​​。

​2. 程序头表(Program Header Table,段头表)​

  • 描述可执行文件或动态库中的​​段(segment)​​(如代码段、数据段),供操作系统​​加载器​​(execve/ld.so)使用。
  • 加载时,操作系统根据程序头表将段映射到内存(如 LOAD 类型的段)
  • ​动态库和可执行文件必须有程序头表​​(否则无法加载),可以没有节头表。

​3. ELF 头

  • e_entry 字段​​:指定程序执行的起始地址(即 _start 函数的地址),加载后会将此地址赋给 ​​PC/RIP​​ 寄存器。

目标文件的节详解

1. 代码与数据节​

​节名​​作用​​常见属性​
.text存储​​代码​​(函数、指令)AX(可执行、只读)
.data存储​​已初始化的全局/静态变量​WA(可写、已初始化)
.bss存储​​未初始化的全局/静态变量​​(实际不占文件空间)WA(可写、未初始化)
.rodata存储​​只读数据​​(如字符串常量、const变量)A(只读)

链接后.text节和.rodata节会合并为代码段,.data节合并为数据段,.bss节合并为bss段


​2. 符号与重定位节​

​节名​​作用​​链接阶段关键性​
.symtab​符号表​​(函数、变量名及其地址/大小)✅ 静态链接必需
.rel.text.text节的​​重定位条目​​(修正代码中的地址引用)✅ 必需
.rel.data.data节的​​重定位条目​​(修正数据中的地址引用)

✅ 必需

符号表的作用:

1.记录符号定义,符号是变量还是函数,以及对应地址

2.标记未定义符号

3.辅助重定位

重定位表的作用:

目标文件中代码和数据中对符号(函数/变量)的引用地址是临时的。重定位表指导链接器如何将这些临时地址替换为​​最终的虚拟地址​​。


​3. 动态链接相关节​​(仅当启用-fPIC编译时存在)

​节名​​作用​​动态库必需​
.got全局偏移表(Global Offset Table)✅ 动态库需要
.plt过程链接表(Procedure Linkage Table)✅ 动态库需要

静态链接的​过程

​(1) 输入文件准备​
  • ​目标文件(.o)​​:含main的目标文件
  • ​静态库(.a)​​:本质是多个目标文件的打包(通过ar工具生成),例如:ar rcs libfoo.a foo.o bar.o # 将foo.o和bar.o打包为libfoo.a
​(2) 链接器(ld)的工作流程​
  1. ​符号解析(Symbol Resolution)​

    • 合并所有目标文件的符号表(.symtab),检查是否存在​​未定义符号​​(标记为U)。
    • ​若存在未定义符号​​:直接报错(如undefined reference to 'printf'),链接失败。
  2. ​节合并(Section Merging)​

    • 将同名节(如.text.data)从不同目标文件合并为​​段(Segment)​​:
      • 所有.text → 代码段(可执行)
      • 所有.data → 数据段(可读写)
      • 所有.bss → BSS段(未初始化数据,不占文件空间)
  3. ​分配虚拟地址(Address Assignment)​

    • 链接器为每个段分配​​最终的虚拟地址​​。例如:

      .text 0x400000 (代码段基地址) .data 0x600000 (数据段基地址)

  4. ​重定位(Relocation)​

    • 根据重定位表(.rel.text/.rel.data)修正代码和数据中对符号的引用:
      • ​修正代码中的地址​​:如call 0x0 → call 0x400100(函数foo的最终地址)。
      • ​修正数据中的指针​​:如mov rax, [0x0] → mov rax, [0x600020](变量var的地址)。
  5. ​生成可执行文件​

    输出一个完整的ELF可执行文件(a.out),包含程序头表(描述如何加载段到内存)。

动态链接的过程​

​1.生成可执行文件时的链接​

  • ​输入文件​​:
    • 目标文件(main.o
    • 动态库(.so,如 libc.so
  • ​静态链接器(ld)的操作​​:
    1. ​符号解析​​:检查 main.o 中的未定义符号(如 printf)是否在动态库的 .dynsym 中。
    2. ​生成 PLT/GOT​​:
      • 在可执行文件中创建 .plt 和 .got.plt 节。
      • 将对动态库函数的调用(如 call printf)改为 call printf@plt
    3. ​记录依赖关系​​:在可执行文件的 .dynamic 段中注明依赖的动态库(如 libc.so.6)。

​2. 运行时动态加载流程​

​(1) 加载可执行文件​
  • ​操作系统​​:
    1. 读取可执行文件的 ​​程序头表​​(Program Header Table),将代码段(.text)和数据段(.data)映射到进程的虚拟地址空间。
    2. 从ELF头中读程序入口,将 PC 寄存器设为 e_entry(入口地址,通常是 _start)。
​(2) 加载动态库​
  • ​动态链接器(ld.so)​​:
    1. 根据 可执行文件的.dynamic 段加载所有依赖的动态库(如 libc.so)到 ​​随机地址​​(ASLR)。
    2. 重定位got表的里变量的地址,函数地址不重定位,有另一套机制

got表和plt表说明

1.当动态库加载进地址空间,ld.so重定位got表中变量的地址,而代码段中对动态库中变量的访问,编译的指令为访问got表中目标变量的地址,如何做到,就是mov eax【pc+偏移量】,偏移量是pc到目标变量GOT条目的偏移​​

2.动态库加载进地址空间,动态链接器不会重定位got表中函数项,因为

在链接时会符号解析,如果main.o中使用了动态库的函数,那么调用函数的指令会从call printf被换成call printf@plt,去跳转plt表对应函数条目

printf@plt:
  jmp func@got ; 跳转got项
  pushq $index       ; 压入重定位表索引(如 printf 在 .rela.plt 中的位置)
  jmp .plt           ; 跳转到动态链接器(ld.so),重定位函数

plt表是在代码段,因为plt是不可更改的,而got在数据段,因为函数项是要动态重定位的,got表中函数项在编译时被编译成plt表中对应函数条目的push指令

第一次调用库函数时,call func@plt 跳转plt对应函数条目,跳转到got项,然后pushq 重定位表索引到队列,调用动态链接器去重定位库函数,将地址写进got,然后调用函数

第二次调用库函数,call func@plt  跳转plt表对应函数条目,跳转got项,然后直接调用函数

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

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

相关文章

PDF 文档结构化工具对比:Marker 与 MinerU

模型训练数据-MinerU一款Pdf转Markdown软件 https://codeyuan.blog.csdn.net/article/details/144315141 在当前大模型&#xff08;LLM&#xff09;和自然语言处理&#xff08;NLP&#xff09;应用快速发展的背景下&#xff0c;如何高效地将 PDF 等非结构化文档转换为结构化数…

shp2pgsql 导入 Shp 到 PostGIS 空间数据库

前言 ❝ shp2pgsql是PostGIS自带的命令行工具&#xff0c;用于将Shapefile文件声称SQL脚本导入到PostGIS空间数据库。 1. 安装 PostGIS 通过Application Stack Builder或者下载单独的PostGIS包进行安装。而shp2pgsql则是与PostGIS工具集成在一起&#xff0c;无需单独下载。该命…

【ISP算法精粹】什么是global tone mapping和local tone mapping?

1. 简介 全局色调映射&#xff08;Global Tone Mapping&#xff09;和局部色调映射&#xff08;Local Tone Mapping&#xff09;是高动态范围&#xff08;HDR&#xff09;图像处理中的两种关键技术&#xff0c;用于将高动态范围图像的亮度值映射到标准动态范围&#xff08;LDR…

虚拟环境中VSCode运行jupyter文件

用VS Code打开jupyter文件&#xff0c;点击右上角 Select Kernel 在正上方会出现这个选择框&#xff0c;选择 Python Environment 会出来所有的虚拟环境&#xff0c;选择要用的环境行

如何计算VLLM本地部署Qwen3-4B的GPU最小配置应该是多少?多人并发访问本地大模型的GPU配置应该怎么分配?

本文一定要阅读我上篇文章&#xff01;&#xff01;&#xff01; 超详细VLLM框架部署qwen3-4B加混合推理探索&#xff01;&#xff01;&#xff01;-CSDN博客 本文是基于上篇文章遗留下的问题进行说明的。 一、本文解决的问题 问题1&#xff1a;我明明只部署了qwen3-4B的模型…

antv/g6 图谱封装配置(二)

继上次实现图谱后&#xff0c;后续发现如果要继续加入不同样式的图谱实现起来太过麻烦&#xff0c;因此考虑将配置项全部提取封装到js文件中&#xff0c;图谱组件只专注于实现各种不同的组件&#xff0c;其中主要封装的点就是各个节点的横坐标&#xff08;x&#xff09;,纵坐标…

从芯片互连到机器人革命:英伟达双线出击,NVLink开放生态+GR00T模型定义AI计算新时代

5月19日&#xff0c;在台湾举办的Computex 2025上&#xff0c;英伟达推出新技术“NVLink Fusion”&#xff0c;允许非英伟达CPU和GPU&#xff0c;同英伟达产品以及高速GPU互连技术NVLink结合使用&#xff0c;加速AI芯片连接。新技术的推出旨在保持英伟达在人工智能开发和计算领…

Qt window frame + windowTitle + windowIcon属性(3)

文章目录 window frame属性window frame的概念1. window frame的影响2. 图片演示3. 代码演示 API接口widget.cpp&#xff08;测试代码&#xff09; windowTitle属性API接口问题 注意点widget.cpp&#xff08;属性用法&#xff09; windowIcon属性API接口啥是窗口图标玩法1. 先…

Git 分支管理:merge、rebase、cherry-pick 的用法与规范

Git 分支管理&#xff1a;merge、rebase、cherry-pick 的用法与规范 在团队开发和个人项目中&#xff0c;合理管理 Git 分支至关重要。merge、rebase 和 cherry-pick 是最常用的三种分支操作命令。本文将介绍它们的基本用法、适用场景及最佳实践规范&#xff0c;帮助大家更高效…

VR全景制作方法都有哪些?需要注意什么?

VR全景制作是将线下实景场景转化为具有沉浸式体验的全景图像的相关技术流程。通过图像处理和软件拼接等手段及技术&#xff0c;可以制作出VR全景图。后面&#xff0c;我们科普详细的VR全景制作方法指南&#xff0c;顺便介绍众趣科技在相关领域提供的支持方案。 选定拍摄地点与准…

计算机系统结构1-3章节 期末背诵内容

Amdahl定律: 加快某部件执行速度所能获得的系统性能加速比&#xff0c;受限于该部件的执行时间占系统中总执行时间的百分比。 加速比依赖于: 可改进比例&#xff1a;在改进前的系统中&#xff0c;可改进部分的执行时间在总的执行时间中所占的比例。 部件加速比&#xff1a;可改…

JS实现直接下载PDF文件

pdf文件通过a标签直接下载会打开页面&#xff0c;所以&#xff0c;请求该文件的blob文件流数据&#xff0c;再通过window.URL.createObjectURL转成链接&#xff0c;就可以直接下载了。 只需要替换url和文件名称就行&#xff0c;文件名的后缀记得要写上pdf&#xff0c;不然会变成…

深度解析Pytest中Fixture机制与实战案例

一、为什么我们需要Fixture&#xff1f; 在某次金融系统重构项目中&#xff0c;我们的测试团队曾遇到这样的困境&#xff1a;随着测试用例增长到500&#xff0c;使用unittest框架编写的测试代码出现了严重的维护问题——setup方法臃肿不堪&#xff0c;测试数据混乱&#xff0c…

文档结构化专家:数字化转型的核心力量

文档结构化专家:定义、职责与行业应用的全方位解析 一、文档结构化的定义与核心价值 文档结构化是将非结构化或半结构化文档(如文本、图像、表格)转换为计算机可处理的规范化数据形式的过程。其核心在于通过语义解析、信息单元划分和标准化格式(如XML/JSON),实现信息的…

Linux系统管理与编程16番外篇:PXE自动化安装部署OpenEuler24.03LTS

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 Preboot Execution Environment 本机服务器操作系统&#xff1a;CentOS7.9.2207 目标服务器安装系统&#xff1a;openEuler-24.03-LTS-SP1-everything-x86_64-dvd.iso 虚拟机&#xff1…

Enhanced RTMP H.265(HEVC)技术规格解析:流媒体协议的新突破

Enhanced RTMP H.265&#xff08;HEVC&#xff09;技术规格解析&#xff1a;流媒体协议的新突破 “每一帧画面都是时间的映射&#xff0c;压缩之后的灵魂&#xff0c;依然能栩栩如生。” 随着流媒体技术的快速发展&#xff0c;视频编码标准不断推陈出新。H.264/AVC虽然已经成为…

Visual Studio Code 改成中文模式(汉化)

1、打开工具软件&#xff08;双击打开&#xff09; 2、软件左边图标点开 3、在搜索框&#xff0c;搜索 chinese 出现的第一个 就是简体中文 4、点击第一个简体中文&#xff0c;右边会出来基本信息 点击 install 就可以安装了&#xff08;记得联网&#xff09;。 5、安装完右…

Linux--初识文件系统fd

01. C/系统调用文件操作 C/系统调用文件操作 02. 文件系统(ext2)结构 Linux ext2文件系统&#xff0c;上图为磁盘文件系统图&#xff08;内核内存映像肯定有所不同&#xff09;&#xff0c;磁盘是典型的块设备&#xff0c;硬盘分区被划分为一个个的block。一个块的大小(有1MB,…

算法中的数学:欧拉函数

1.相关定义 互质&#xff1a;a与b的最大公约数为1 欧拉函数&#xff1a;在1~n中&#xff0c;与n互质的数的个数就是欧拉函数的值 eg&#xff1a; n1时&#xff0c;欧拉函数的值为1&#xff0c;因为1和1是互质的 n2是&#xff0c;值为2&#xff0c;因为1和2都是互质的 积性函数&…

BaseDao指南

1. BaseDao类 import java.sql.*;/*** 通用的工具类 ,负责连接数据&#xff0c; 执行增删改查的通用方法*/ public class BaseDao {private Connection connection;private PreparedStatement pstm;private ResultSet rs;/*** 建立数据库连接** return*/public Boolean getCon…