在32位机器上,总共有4G大小的虚拟地址空间,其中0-3G是给应用程序使用,3-4G是给内核使用。

在64位机器上,目前还不完全支持64位地址宽度,常见的地址长度有39(512GB)和48位(256TB),目前我使用的模拟器采用的是39位的地址宽度,这样的话用户空间和内核空间各占512GB的地址空间。

当一个应用程序在用户跑起来的时候,它内部是如何正常运行的,通过一个简单的例子详细说明下。

#include <stdio.h>
#include <malloc.h>static int global_data=1;
static int global_data1;
int bss_data;
int bss_data1;int main()
{int stack_data = 1;int stack_data1 = 2;int data[200*1024];static int data_val=1;int* malloc_data=malloc(10);int* malloc_data1=(int*)malloc(300);int* malloc_data2=(int*)malloc(300*1024);// stack segmentprintf("stack segment!\n");printf("\t stack_data=0x%lx\n",&stack_data);printf("\t stack_data1=0x%lx\n",&stack_data1);// heap segmentprintf("heap segment!\n");printf("\t malloc_data=0x%lx\n",malloc_data);printf("\t malloc_data1=0x%lx\n",malloc_data1);printf("\t malloc_data2=0x%lx\n",malloc_data2);//code segmentprintf("code segment!\n");printf("\t code_data=0x%lx\n",main);//data segmentprintf("data segment!\n");printf("\t global_data=0x%lx\n",&global_data);printf("\t global_data1=0x%lx\n",&global_data1);printf("\t data_val=0x%lx\n",&data_val);//bss segmentprintf("bss segment!\n");printf("\t bss_data=0x%lx\n",&bss_data);printf("\t bss_data1=0x%lx\n",&bss_data1);return 0;
}

为了更好的实验,我们需要在ARM64的机器上运行上述的测试例子。然后打印各个段的地址。

root:/ # ./data/vma
stack segment!stack_data=0x7fe8a41e24stack_data1=0x7fe8a41e20
heap segment!malloc_data=0x356db9d0malloc_data1=0x356db9f0malloc_data2=0x6ff3187010
code segment!code_data=0x400620
data segment!global_data=0x48b960global_data1=0x48d380data_val=0x48b964
bss segment!bss_data=0x48e448bss_data1=0x48e44c

我们根据各个段打印的地址来用一张图描述下各个段的位置。目前描述的是ARM64架构,可能不同架构不是一样

我们将ARM64的用户空间放大,就可以清晰的看见各个段在整个用户空间的位置。

  • 代码段是用户虚拟地址空间的最低位置,代码段就是我们code所在的位置
  • 在代码段的位置上面就是数据段,数据段就是全局初始化的变量。
  • 数据段的位置就是BSS段,BSS段就是未初始化的全局变量。
  • Stack段就是函数调用的局部变量,或者函数中定义的局部数组。可以看到栈是从高地址往下增长的。
  • Heap段就是对应的malloc申请的区域,从实验结果上来看heap段正好位于用户空间中间部分,而且是从下往上增长的。
  • Mmap区域,就是我们使用mmap映射那段区域。当使用malloc申请的大于128K,则会使用mmap区域的。

以上实验是针对ARM64架构的实验结果的。大家有兴趣的话可以研究下32位系统。我这里直接给出32系统的结果,当然了也是实验的结果,这是N年之前在32的ubuntu机器做的结果

对应的结果如下

可以看到和ARM64表现是一样的。

VMA(Virtual Memory Area)

上述说的各个段最终还需要映射到具体的物理内存的,而在内核中使用VMA来描述各个段的。我们可以通过cat /proc/pid/maps命令来对应下上面的实验结果

大家可以去对对地址是否落在对应的区域。

内核通过vma来描述各个段,而各个vma会通过链表或者红黑树链接在一起,会将链表的头放在mm_struct结构中的。

这里不具体描述vma了,有兴趣的可以去查询相关的code去看。大概描述下vma的定义

这里我们只需要掌握用户空间的各个段的布局,心中知道代码段,数据段,stack,heap段各个的位置。以及各个段在内核中通过vma去描述,而各个vma是通过链表或者红黑树链接一起的。链表头会挂载mm_struct的mmap中,红黑树的的头挂在mm_struct的mmap_rb上。

链表是为了插入方便,而红黑树是为了查找方便。

根据crash学习用户空间程序内存布局相关推荐

  1. linux应用程序内存布局

    1.linux应用程序内存布局 从低地址到高地址分别为:代码段.数据段.BSS段.堆.栈 对向高内存地址生长,栈想低内存地址生长 linux中所有的应用程序都是这个布局,每个应用程序都是从0x8048 ...

  2. 深入理解C程序内存布局

    1.堆和栈的区别,堆和栈的最大限制 堆主要用来分配动态内存,操作系统提供了malloc等内存分配机制来供程序员进行堆内存的分配,同时,堆内存的释放需要程序员来进行.malloc分配的是虚拟地址空间,和 ...

  3. 详细讲解从用户空间申请内存到内核如何为其分配内存的过程

    Linux内存管理 摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法.力求从外到内.水到渠成地引导网友分析Linux ...

  4. linux程序内存布局,关于Linux中程序的内存布局

    我有一些关于Linux中的程序的内存布局的问题. 我知道从各种来源(我正在读"从头开始编程"),每个部分都加载到它自己的内存区域. 文本部分首先在虚拟地址0x8048000处加载, ...

  5. C/C++程序内存布局(data段,bss段,text段)以及static关键字详解

    目录 1.内存布局 1.1 data段(可读可写) 1.2 text段(只读) 1.3 bss段(可读可写) 1.4 堆区 1.5 栈区 1.6全局区/静态区 1.7 字符串常量区 1.8 代码区 1 ...

  6. 08 内存分配和程序内存布局

    1 Memory Model 类型 描述 大小 int 整形数字 4B short 整形数字 2B long 整形数字 8B char 字符 1B float 浮点型 4B double 浮点型 8B ...

  7. linux内存布局及页面映射

    在Linux系统中,以32bit x86系统来说,进程的4GB内存空间(虚拟地址空间)被划分成为两个部分 ------用户空间和内核空间,大小分别为0-3G,3-4G. 用户进程通常情况下,只能访问用 ...

  8. 【Linux 内核 内存管理】内存管理架构 ② ( 用户空间内存管理 | malloc | ptmalloc | 内核空间内存管理 | sys_brk | sys_mmap | sys_munmap)

    文章目录 一.用户空间内存管理 ( malloc / free / ptmalloc / jemalloc / tcmalloc ) 二.内核空间内存管理 1.内核内存管理系统调用 ( sys_brk ...

  9. 【C 语言】内存管理 ( 动态内存分配 | 栈 | 堆 | 静态存储区 | 内存布局 | 野指针 )

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  10. Linux 用户空间和内核空间指的是什么?

    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间.两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数 ...

最新文章

  1. Note:类(Class)
  2. 【Python面试】 说说Python模块主要分哪三类?
  3. *PAT_B_1014_Java(20分)
  4. masked_fill【将mask中值为True的位置对应的待填充的张量设置为value值】
  5. 何恺明组《Designing Network Design Spaces》的整体解读(一篇更比六篇强)
  6. AOP——基于AspectJ的注解来实现AOP操作
  7. 他爱的只是你爱他(一)
  8. tomcat启动过程报the JDBC Driver has been forcibly unregistered问题的修复过程
  9. 生来只为丈量天空,开普勒的传奇一生
  10. 树莓派做网络代理_树莓派使用Proxy代理
  11. 商业智能BI与业务管理决策思维之二:业务结构分析
  12. 视频号容易被官方封号的违规操作,你中招了吗?
  13. 三级网络技术备考重点之中小型网络系统总体规划与设计
  14. 签到签退功能的实现-01
  15. 教育行业分享-基础篇
  16. 搭建一个全功能 GPS 追踪系统
  17. jar包 加密 ----xjar (亲测可用)
  18. VIC之PL192使用介绍
  19. Python入门自学进阶-Web框架——16、Django登录/注册
  20. Vmware Linux虚拟机全屏

热门文章

  1. 二进制GCD算法解析
  2. 数据库基础(2):简单查询和连接查询
  3. 远程登录 - telnet、mstsc等工具的使用及遇到的问题
  4. @Autowired与@Resource用法
  5. c语言野王验证,王者荣耀:“野王是如何炼成的?”,方法很简单,6个字而已...
  6. Maven常用命令 - 构建反应堆中指定模块
  7. 从0开始运行flutter helloworld笔记
  8. DevExpress控件TExtLookupComboBox实现多列模糊匹配输入的方法
  9. JavaScript 常用功能总结
  10. github使用介绍