首页 > 系统相关 >ELF加载内存

ELF加载内存

时间:2024-09-18 10:28:37浏览次数:9  
标签:初始化 只读 ELF 内存 全局变量 加载

当一个 ELF(Executable and Linkable Format)文件加载到内存后,它的各个段会根据文件中的描述被映射到内存的不同区域。ELF 文件被广泛用于 Unix/Linux 系统中的可执行文件、共享库和目标文件。典型的 ELF 文件包含多个段(sections),这些段被加载到内存中用于不同的目的,例如代码、数据、堆栈等。

ELF 文件的段(Section)与内存布局

ELF 文件在磁盘上有多个段,这些段在被加载到内存后,操作系统将它们映射到不同的虚拟内存区域。不同的段有不同的功能,它们通常包括代码段、数据段和其他需要加载的内容。

ELF 文件的主要段和内存中的分布

在内存中,ELF 文件通常会被分为以下几个关键段:

  1. .text 段(代码段)

    • 功能:该段存放可执行的程序代码,即编译后的指令。
    • 权限:一般标记为只读和可执行r-x)。
    • 内存位置:通常位于程序映射的最低虚拟地址附近,且通常是页面对齐的(比如 4KB 对齐)。
    • 映射到内存后:该段加载到内存后,系统将其标记为可执行的内存区域,而不会允许写入操作。

    内存布局示意图:

    0x08048000: (低地址)
        ↓
        .text 段(代码段)
        存储程序的可执行代码
        [r-x] (只读 + 可执行)
        ↑
    
  2. .rodata 段(只读数据段)

    • 功能:该段存储程序的只读数据,如字符串常量、全局常量等。
    • 权限:标记为只读r--),防止运行时修改。
    • 内存位置:通常紧随 .text 段之后加载到内存中。

    内存布局示意图:

    0x08049000: 
        ↓
        .rodata 段(只读数据段)
        存储只读数据(例如字符串常量)
        [r--] (只读)
        ↑
    
  3. .data 段(数据段)

    • 功能:该段存储初始化的全局变量和静态变量。
    • 权限:标记为可读和可写rw-),因为这些变量在程序运行过程中可能会被修改。
    • 内存位置:通常位于 .rodata 段之后。

    内存布局示意图:

    0x0804A000: 
        ↓
        .data 段(数据段)
        存储初始化的全局变量
        [rw-] (可读 + 可写)
        ↑
    
  4. .bss 段(未初始化数据段)

    • 功能:该段存储未初始化的全局变量和静态变量。在 ELF 文件中,.bss 段并不占据磁盘空间(只在内存中分配),其大小在 ELF 文件头中描述。
    • 权限:标记为可读和可写rw-),因为这些变量可能会被修改。
    • 内存位置:通常位于 .data 段之后。

    内存布局示意图:

    0x0804B000: 
        ↓
        .bss 段(未初始化数据段)
        存储未初始化的全局变量
        [rw-] (可读 + 可写)
        ↑
    
  5. 堆(Heap)

    • 功能:堆是动态分配内存的区域,用于程序在运行时通过 malloc 等动态分配函数申请的内存。
    • 权限:标记为可读和可写rw-)。
    • 内存位置:堆区域位于 .bss 段之后,通常会随着程序的运行动态增长,操作系统通过系统调用(如 brksbrk)来调整堆的大小。

    内存布局示意图:

    0x0804C000:
        ↓
        堆
        动态内存分配区域
        [rw-] (可读 + 可写)
        ↑
    
  6. 栈(Stack)

    • 功能:栈是用于函数调用时存储局部变量、返回地址等信息的区域。
    • 权限:标记为可读和可写rw-),并具有自动增长的特点(通常栈向下增长)。
    • 内存位置:栈通常位于虚拟地址空间的高地址处,并向低地址方向增长。

    内存布局示意图:

    高地址:
        ↓
        栈(Stack)
        [rw-] (可读 + 可写)
        ↑
    

ELF 文件的段加载和布局示意图

内存中 ELF 文件加载后的典型布局示例如下:

内存高地址
+----------------------------+ 
|         栈段 (Stack)        |  ← 栈从高地址向低地址增长
+----------------------------+
|            ...              |
+----------------------------+
|         堆段 (Heap)         |  ← 堆从低地址向高地址增长
+----------------------------+
|         .bss 段             |  ← 未初始化数据
+----------------------------+
|         .data 段            |  ← 已初始化的全局变量
+----------------------------+
|        .rodata 段           |  ← 只读数据
+----------------------------+
|         .text 段            |  ← 可执行代码
+----------------------------+
内存低地址
  • :位于高地址,向低地址方向增长。栈用于存储函数调用的局部变量和返回地址等信息。
  • :位于 .bss 段之后,随着动态内存分配不断增长。堆用于存储运行时动态分配的内存。
  • .bss 段:存储未初始化的全局变量和静态变量。
  • .data 段:存储已初始化的全局变量和静态变量。
  • .rodata 段:存储只读数据(如常量字符串、常量数组等)。
  • .text 段:存储程序的可执行代码。

各个段的权限说明

  • .text 段:只读且可执行,存放程序的指令。
  • .rodata 段:只读,存放只读数据。
  • .data 段:可读可写,存放已初始化的全局变量和静态变量。
  • .bss 段:可读可写,存放未初始化的全局变量和静态变量。
  • :可读可写,用于动态内存分配。
  • :可读可写,用于函数调用时存储局部变量、返回地址等。

段加载的过程

  1. 解析 ELF 文件头:加载器首先读取 ELF 文件头,了解文件的格式、段的数量和位置等信息。

  2. 加载各个段:根据程序头表(Program Header Table)中描述的段信息,加载器将各个段(如 .text.data.bss)从磁盘加载到内存,并设置相应的访问权限。

  3. 内核映射内存区域:操作系统的加载器为 ELF 文件中的各个段分配虚拟地址空间,并通过页表将虚拟地址映射到实际的物理内存。还会为堆和栈分配内存。

  4. 权限设置:根据段的类型和需求,加载器为每个段设置合适的权限。例如,.text 段被标记为可执行但不可写,.data 段可读可写等。

总结

ELF 文件加载到内存后,各个段的分布和权限如下:

  • .text 段:存放可执行代码,通常位于内存低地址,具有只读和可执行权限。
  • .rodata 段:存放只读数据,具有只读权限。
  • .data 段:存放初始化的全局变量,具有读写权限。
  • .bss 段:存放未初始化的全局变量,

标签:初始化,只读,ELF,内存,全局变量,加载
From: https://www.cnblogs.com/lihaoxiang/p/18418022

相关文章

  • C语言:结构体在内存中存储(内存对齐)
    一、结构体是什么1.结构体的声明2.结构体的初始化二、结构体的内存对齐1.对齐规则 2.为什么存在内存对齐总结前言结构体是重要的知识点,其中,结构体的内存对齐是较重要的部分(本人使用的编译器是VisualStudio2022,下面介绍的对齐数也是以VS默认的8为标准),对后面学习数据......
  • C语言:整数和浮点数在内存中的存储--(超好理解)
    目录一、整数在内存中的存储(有符号整数)1.设置反码和补码的的目的二、浮点数在内存中的存储1.浮点数取的过程2.例题解析总结目前学习到C语言的各种数据类型在内存中的存储的方式和过程,自己初学的时候下了很多时间去学习理解,为了帮助和自己一样的在第一次初学C语言存储......
  • 请解释什么是CDN,以及它如何提高网站加载速度。
    CDN是什么?CDN(ContentDeliveryNetwork,内容分发网络)是一种广泛使用的网络基础设施,旨在提高互联网内容的传输效率。CDN通过在全球范围内布置多个边缘节点服务器(EdgeServers),将内容缓存到离用户最近的地方,从而减少了因地理位置造成的延迟,提高了内容的加载速度。CDN的工作原......
  • 操作系统知识强化内存映射文件(25王道)
    内存映射文件本文根据25王道操作系统内存映射文件这一章所作跟课笔记什么是内存映射文件首先来看看什么是内存映射文件。简单来说,这是操作系统向上层的程序员提供的一个系统调用功能。通过这个功能,程序员可以很方便的去访问文件数据,另外这个功能也可以很方便的让多个进程......
  • 进程的内存分配
    在操作系统中,进程的内存分配是指操作系统为每个进程管理和分配所需的内存资源。内存管理是操作系统的核心功能之一,它涉及到为进程提供虚拟内存、物理内存分配、页表管理、以及地址转换等操作。操作系统通过虚拟内存机制,使每个进程都可以认为自己拥有独立的、连续的内存空间。1.......
  • 深入剖析:C++类对象的内存布局与优化
    深入剖析:C++类对象的内存布局与优化引言在C++编程中,理解类对象的内存布局对于优化内存使用和提高程序性能至关重要。本文将详细介绍C++类对象的内存布局,包括数据成员、虚函数表指针以及静态变量和静态方法在内存中的位置。通过这些知识,我们可以更好地设计和优化我们的类结......
  • Qt加载天地图离线api开发包/从官网趴地图js代码/费了九牛二虎之力终于搞定
    一、前言说明网上关于如何趴天地图离线api文件的文章,只有少量的两三篇,而且几乎没有说全和说对,搞得评论也是一片懵逼,这里不行那你不行,思路可以借鉴就是。索性花了点时间,自己研究了如何从官网一步步趴下来js文件,最终所有离线能使用的功能全部搞定,也根本不会有http等访问的情况出现,......
  • 前端JavaScript面试重难点: 闭包+内存泄漏+垃圾回收机制
    前置知识!!!闭包是Javascript语言的一个重难点,也是它的特色,很多高级应用都要依靠闭包来实现。在各种专业文献上学习"闭包"的时候,就一个感觉–“抽象”!特别是学习内存泄漏的时候,没想明白为什么使用闭包的时候不及时清除函数中的元素会导致内存泄漏,直到我的......
  • JVM 内存
    目录堆栈默认垃圾回收策略垃圾回收参数G1垃圾回收查看内存的命令堆栈堆:存储对象和数组,堆大小动态分配(-Xms、-Xmx),线程共享,垃圾回收栈:存储局部变量、方法参数、方法栈,相对较小(-Xss),方法完成时释放,线程私有堆栈大小配置-Xmx:设置JVM最大可用内存,默认系统内存的1/4,最大......
  • 支持外部内存功能的STL容器使用方法分享
    一、分享简介    C++的STL支持了多种容器供开发者操作,然而这些容器使用的是系统内存,使用者无法直接管理。边缘端的嵌入式设备通常会要求对使用的内存进行管理,因此封装出支持外部内存功能的STL容器就显得十分必要。本案例针对被封装容器的使用方法进行了经验分享,具体涉及3......