前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >根据crash学习用户空间程序内存布局

根据crash学习用户空间程序内存布局

作者头像
DragonKingZhu
发布2020-04-10 14:35:49
4870
发布2020-04-10 14:35:49
举报
文章被收录于专栏:Linux内核深入分析

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

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

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

代码语言:javascript
复制
#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 segment
    printf("stack segment!\n");
    printf("\t stack_data=0x%lx\n",&stack_data);
    printf("\t stack_data1=0x%lx\n",&stack_data1);

    // heap segment
    printf("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 segment
    printf("code segment!\n");
    printf("\t code_data=0x%lx\n",main);

    //data segment
    printf("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 segment
    printf("bss segment!\n");
    printf("\t bss_data=0x%lx\n",&bss_data);
    printf("\t bss_data1=0x%lx\n",&bss_data1);

    return 0;
}

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

代码语言:javascript
复制
root:/ # ./data/vma
stack segment!
         stack_data=0x7fe8a41e24
         stack_data1=0x7fe8a41e20
heap segment!
         malloc_data=0x356db9d0
         malloc_data1=0x356db9f0
         malloc_data2=0x6ff3187010
code segment!
         code_data=0x400620
data segment!
         global_data=0x48b960
         global_data1=0x48d380
         data_val=0x48b964
bss segment!
         bss_data=0x48e448
         bss_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上。

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • VMA(Virtual Memory Area)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档