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

linux进程的内存空间映射(段)

Linux进程的内存空间映射

在 Linux 中,每个进程的内存空间是一个虚拟地址空间,操作系统通过内存映射机制(Memory Mapping)将不同的内存区域分配给不同类型的资源和需求。内存空间映射决定了进程如何访问不同类型的内存,包括程序代码、数据、堆栈、共享库、内核提供的虚拟内存等。

1. 进程内存空间结构

Linux 进程的内存空间是按照虚拟内存模型来管理的。虚拟内存将进程的内存空间划分为不同的区域,每个区域有不同的用途和属性。典型的 Linux 进程的内存空间结构从低地址到高地址大致分为以下几部分:

用户空间 (User Space)

  1. 程序代码段 (Text Segment):
  • 存放程序的可执行代码。
  • 通常是只读的,以避免代码被修改。
  • 在内存映射中,通常标记为 r-xp(只读可执行)。
aaaadc650000-aaaadc651000 r-xp 00000000 b3:02 521701    /home/guol/app3
  1. 数据段 (Data Segment):
  • 存储程序初始化的全局变量、静态变量等数据。
  • 分为只读数据段和可读写数据段。
  • 数据段的内容在程序启动时已经初始化,可以修改。
aaaadc660000-aaaadc661000 r--p 00000000 b3:02 521701    /home/guol/app3
aaaadc661000-aaaadc662000 rw-p 00001000 b3:02 521701    /home/guol/app3
  1. 堆 (Heap):
  • 用于动态分配内存,通过 mallocfree 等函数进行管理。
  • 堆的大小在程序运行时动态增长或缩小。
  • 通常由 brk 系统调用来管理内存的分配。
aaab080f4000-aaab08115000 rw-p 00000000 00:00 0     [heap]
  1. 栈 (Stack):
  • 用于存放函数调用时的局部变量、返回地址和函数调用时的上下文等。
  • 栈的大小通常是有限制的,超过栈的最大空间可能导致栈溢出(stack overflow)。
fffffdc1f000-fffffdc40000 rw-p 00000000 00:00 0     [stack]
  1. 内存映射文件 (Mapped Files):
  • 用于映射共享库(如 libc.solibstdc++.so)和其他需要动态加载的文件(如自己写的库文件libmyCppLib.so)。
  • 共享库的代码段通常是只读可执行的。
ffff8b000000-ffff8b189000 r-xp 00000000 b3:02 57279     /usr/lib/aarch64-linux-gnu/libc.so.6
ffff90c30000-ffff90e3a000 r-xp 00000000 b3:02 54038     /usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.30
ffff91020000-ffff91021000 r-xp 00000000 b3:02 1172813   /home/guol/cmaketest/build/libmyCppLib.so
  1. 共享内存 (Shared Memory):
  • 用于不同进程之间的内存共享。
  • 共享内存可以由多个进程同时访问,并且可能会出现在进程的映射区域中。
ffff8b198000-ffff8b19c000 r--p 00188000 b3:02 57279     /usr/lib/aarch64-linux-gnu/libc.so.6
ffff8b19c000-ffff8b19e000 rw-p 0018c000 b3:02 57279     /usr/lib/aarch64-linux-gnu/libc.so.6
  1. 虚拟动态共享对象 (VDSO):
  • 这是由内核提供的一种特殊机制,用于提高系统调用的效率,避免频繁的上下文切换。
  • 内核将某些常用的系统调用(如 gettimeofday())映射到用户空间的 vdso 区域,用户空间直接调用该区域中的代码,减少进入内核的开销。
ffff8b203000-ffff8b204000 r-xp 00000000 00:00 0     [vdso]
  • 信号机制中,用户定义的信号处理函数就是用的这块内存空间映射来完成信号处理函数完成后跳转到改地方的函数再进入内核恢复进程上下文的(详细见linux信号机制文章)。
  1. 虚拟变量区域 (VVAR):
  • 存放由内核提供的虚拟变量(如系统启动时间等)供用户进程使用。
  • 该区域中的变量由内核管理,用户进程可以直接读取。
ffff8b201000-ffff8b203000 r--p 00000000 00:00 0     [vvar]
  1. 内存映射区域 (Memory Mapped Area):
  • 用于 mmap() 系统调用,通常用于内存映射文件或匿名内存映射(如共享内存区域)。
  • 这部分内存的内容通常是动态分配的。
0x7fffffff6000-0x7fffffff7000 rw-p 00000000 00:00 0 [anon]
  1. 实际分布(链接了自制的动态链接库libmyCppLib.so
    在这里插入图片描述

内核空间 (Kernel Space)

  • 内核空间是操作系统内核使用的内存区域,用户空间无法直接访问。
  • 内核地址空间通常位于高地址,用户进程无法直接读取或写入内核空间。内核通过系统调用、陷入和中断等机制与用户空间进行交互。
  • 在 64 位架构中,内核空间的虚拟地址通常从 0xffff000000000000 开始,分配给内核使用。

2. 特殊区域

  • [vvar]:虚拟变量区(Virtual Variable Area)。内核将一些常用的内核变量(如系统时间、进程 ID 等)映射到该区域,用户进程可以快速访问,减少对内核的访问。

  • [vdso]:虚拟动态共享对象区(Virtual Dynamic Shared Object)。由内核提供,用户空间可以直接调用其中的一些函数(如 gettimeofday())来避免进入内核态。

3. 进程内存映射表

每个进程都有一个 /proc/[pid]/maps 文件,记录了该进程的内存映射情况。通过 cat /proc/[pid]/maps 命令可以查看进程的内存映射信息。

该文件包含每个内存区域的以下信息:

  • 地址范围(虚拟地址的开始和结束)
  • 权限(r 读、w 写、x 执行、p 私有)
  • 偏移量
  • 设备(设备号)
  • inode(文件的索引节点号)
  • 区域的名称(如共享库、堆、栈、匿名映射等)

4. 动态链接器的进入

  1. 在elf文件(linux下的可执行程序)中的.got表中存放了动态链接库的入口地址,同样.got存放的第一个地址一直是0(undefine),其他空间存放的是其他库函数的入口地址,将实现动态绑定(即运行时动态链接器绑定)。
  2. .got存放的第一个地址一直是00地址作为目的地跳转时则会触发异常,进入内核态,然后内核会将控制权交给动态链接器进行库函数的动态链接(这样就完成了库函数的动态链接绑定)。
  • udf 指令(即要跳转的指令地址为0)并不是导致程序跳转到地址 0,而是触发了一个异常(未定义指令异常),并将控制权交给动态链接器。

在这里插入图片描述

相关文章:

  • Spring Boot 常用注解详解
  • 宠物行业研究系列报告
  • 在大数据分析中如何选择合适的算法和模型
  • 黑马点评—短信登陆商户查询缓存
  • C++:使用 SFML 创建强化学习迷宫场景
  • JAVA EE初阶 JVM
  • nginx作为下载服务器配置
  • FPGA开发要学些什么?如何快速入门?
  • 第8章作业
  • Nginx知识详解(理论+实战更易懂)
  • 【十一】Golang 指针
  • 免费开源多平台轻量级本地视频工具,支持Windows、Android
  • 面试知识点2
  • Android 11.0 WiFi连接默认设置静态IP地址功能实现
  • mapbox基础,使用geojson加载Fill面图层
  • 2.20学习
  • minio作为K8S后端存储
  • 悬挂引用,智能指针 裸指针 悬挂指针
  • 项目汇报PPT转视频制作 | 有字幕和配音版
  • EasyPoi系列之通用导入接口设计
  • 中国纪检监察报刊文:要让劳动最光荣成为社会的崇高风尚
  • 上海“生育友好岗”已让4000余人受益,今年将推产假社保补贴政策
  • AI应用大盘点:谁暴涨?谁掉队?
  • 宣称防老年痴呆的“原装进口”保健品McPee被指涉假,未获澳方销售批准
  • 谁将主导“视觉大脑”?中国AI的下一个超级赛道
  • 起底网红热敷贴“苗古金贴”:“传承人”系AI生成,“千年秘方”实为贴牌货