ELF文件中的“节“与“段“,如何与虚拟地址空间中的“分页“和“分段“产生联系?

为了理清它们的关系,必须先说明:

ELF文件中的"段(Segment)"x86 CPU硬件上的"分段(Segmentation)" ,虽然中文和英文名字极其相似,但它们没有任何直接关系

静态视角下的 ELF

在硬盘上,ELF 文件同时具备两种视角:

  1. 链接视图(以"节 Section"为主):
    这是给编译器和链接器 看的。比如存放代码的 .text 节,存放初始化全局变量的 .data 节,存放未初始化变量的 .bss 节。它们切分得非常细致,方便链接器拼图。
  2. 执行视图(以"段 Segment"为主):
    这是给操作系统加载器(Loader)看的。操作系统在运行程序时,根本不关心你这里面有几个"节"。它只关心内存权限。因此,ELF 文件内部会有一个"程序头表(Program Header Table)",它把具有相同权限的"节"合并成一个"段(Segment)"。
  • 比如:把 .text.rodata(只读数据)合并成一个属性为 可读、可执行 (R-E)LOAD Segment
  • .data.bss 合并成一个属性为 可读、可写 (R-W)LOAD Segment

结论 1: ELF 中的"段(Segment)"纯粹是一个软件层面的数据结构打包概念,与 CPU 的硬件分段单元(Segmentation)毫无瓜葛。


操作系统加载 ELF (mmap)

当敲下 ./my_program 回车时,操作系统开始工作。它如何把 ELF 的"段"与虚拟地址空间联系起来?

操作系统读取 ELF 的执行视图(LOAD Segments),然后在进程的虚拟地址空间 中划分出一块块对应的区域(在 Linux 源码中叫 VMA,Virtual Memory Area)。

这个过程是通过一个叫做 mmap 的系统调用完成的。

  • 操作系统说:"ELF 文件的 LOAD Segment 1(包含代码),你应该被放在虚拟地址的 0x4000000x401000,权限是只读和执行。"
  • 这个时候,程序还没有真正进入物理内存(RAM)。操作系统只是在虚拟地址空间里"占了个座",画了一张饼。

分页机制,从虚拟地址到物理内存 (Paging)

现在的状态是:进程拥有了虚拟地址,ELF文件依然躺在硬盘上,物理内存里什么都没有。

当 CPU 的指令寄存器(RIP)指向 0x400000 准备执行第一条指令时,真正的联系发生了:

  1. 缺页中断(Page Fault): CPU 通过逻辑地址(等于虚拟地址)去访问内存。它去查分页表(Page Table) ,发现这个虚拟地址 0x400000 并没有对应的物理内存页!于是 CPU 触发一个"缺页中断",暂停当前程序,呼叫操作系统内核。
  2. 按需调页(Demand Paging): 操作系统内核接管后,查看记录,发现 0x400000 这个虚拟地址对应的是硬盘上 ELF 文件的 LOAD Segment 1 的起始位置。
  3. 加载与映射: 操作系统赶紧从物理内存(RAM)中找一个空闲的物理页(Physical Page,通常是 4KB)。然后把硬盘上 ELF 文件对应的那 4KB 数据复制到这个物理页中。
  4. 更新页表: 操作系统更新当前进程的分页表,写下记录:"虚拟地址 0x4000000x400FFF,对应物理内存的 页框 X"。
  5. 恢复执行: 操作系统把控制权交还给程序,CPU 再次尝试访问 0x400000。这一次,分页单元顺利地通过页表找到了物理内存,指令成功执行。

结论 2: ELF 的"段"决定了虚拟地址空间的布局;而"分页(Paging)"则是连接虚拟地址与物理内存、并按需将 ELF 内容搬运到内存中的底层搬运工


总结

  • 硬件分段(Segmentation): 在 Linux 中被彻底架空(基址设为 0),只负责把逻辑地址原封不动地变成虚拟地址。
  • ELF 节(Section): 细粒度的代码/数据分类,给链接器看。
  • ELF 段(Segment / Program Header): 多个 Section 的集合,按权限分类,操作系统依据它来规划虚拟地址空间的布局。
  • 硬件分页(Paging): 负责把虚拟地址空间切成 4KB 的小块(页),并在程序实际运行时,把 ELF 文件的内容一点点搬进物理内存
相关推荐
我先去打把游戏先1 小时前
Ubuntu虚拟机(服务器版本)Git卸载完全教程——彻底移除与清理配置
服务器·git·单片机·嵌入式硬件·物联网·ubuntu·51单片机
着迷不白1 小时前
四、Linux 文件权限+sudo权限委派+IO重定向+vim高级
linux·运维·服务器
WhoAmI1 小时前
Linux 服务器挂载 LVM 逻辑卷全流程记录与问题排查
linux·服务器
zincsweet2 小时前
进程同步与通信:System V 消息队列 + 信号量一站式解析
linux
quan_泉2 小时前
DIDCTF 取证初学者
java·服务器·前端
RisunJan2 小时前
Linux命令-nohup(使进程忽略挂起(HUP)信号并在后台继续运行)
linux·运维·服务器
kebidaixu2 小时前
板级设备树驱动修改实战:从PWM到CAN,释放GPIO的完整指南
linux
爱喝水的鱼丶2 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇)第三篇:SAP ALV 报表样式定制:字段布局与交互功能配置
服务器·开发语言·学习·交互·sap·abap