linux-程序内存分布

linux 内存模型

1
2
3
4
5
6
【kernel virtual memory                  】
【user stack (向下) 】
【memory-map/share-memory(向上) 】
【running heap(向上) 】
【read/write segment(.data .bss) 】
【read_only segment(.init .text .rodata) 】

说明:

已初始化的全局变量存储在.dada数据段;为初始化的全局变量位于.bss为初始化数据段。
静态全局变量也在.data数据段
局部变量在栈上,静态局部变量,并不是在调用函数时分配,并不是在函数返回时释放,
其跟全局变量一样静态分配,在.data数据段,但作用域只在函数中 const 修饰的变量在
.rodata只读段,只读段与.text在同一个segment。

  1. 代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。
    这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段
    为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
    程序在被载入内存后,会被分为很多小的区(section),有一个rodata区(也就是常量区),
    常量区的数据内存中的位置为代码段,存放的数据为字符串、const修饰的常量(全局的或是静态的,
    odata区,而这个字符串的地址也就是指针s存放在数据段中(程序载入内存中为.data区)。
    再如,static char *const s=”hello,world”;那么这时候不仅”hello,world”字符串存放在rodata区,
    指针s也同样。
  2. 数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量或者静态变量的
    一块内存区域。数据段属于静态内存分配。原则上数据段所对应的内存区数据是可以改变的。
    这里没有提到局部变量,这是因为局部变量一般都存放在栈中。局部变量不管是否有const修饰
    都存放在栈中,例如char *const lcp=”999”;字符窜”999”存放在代码段的rodata区,这个没有说的,
    而它对应的地址lcp指针存放在栈中;
  3. BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
    BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。例如全局变量int i;
    静态变量static int si;都存放在这里面。
  4. 堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
    当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);
    当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减),要注意的是,
    当分配的数据大小操作内核的限制时,内核采用匿名映射的方式实现而不是从堆中分配内存。
  5. 栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”
    中定义的变量(但不包括static声明的变量,static意味着在数据段或代码段中存放变量)。
    除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,
    函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。
    从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

在进程被载入内存中时,基本上被分裂成许多小的节(section)。我们比较关注的是几个主要的节:

  1. .text 节
    .text 节基本上相当于二进制可执行文件的.text部分,它包含了完成程序任务的机器指令。
    该节标记为只读,如果发生写操作,会造成segmentation fault。在进程最初被加载到内存中开始,该节的大小就被固定。
  2. .data 节
    .data节用来存储初始化过的变量,如:全局int a =0 ; 该节的大小在运行时固定的。
  3. .bss 节
    栈下节(below stack section ,即.bss)用来存储为初始化的变量,如:int a; 该节的大小在运行时固定的。
  4.  堆节
    堆节(heap section)用来存储动态分配的变量,位置从内存的低地址向高地址增长。内存的分配和释放通过malloc() 和 free() 函数控制。
  5.  栈节
    栈节(stack section)用来跟踪函数调用(可能是递归的),在大多数系统上从内存的高地址向低地址增长。
    同时,栈这种增长方式,导致了缓冲区溢出的可能性。
  6. .rodata节
    常量区,全局或静态const变量、指针存放区。
  7. 环境/参数节
    环境/参数节(environment/arguments section)用来存储系统环境变量的一份复制文件,
    进程在运行时可能需要。例如,运行中的进程,可以通过环境变量来访问路径、shell 名称、主机名等信息。
    该节是可写的,因此在格式串(format string)和缓冲区溢出(buffer overflow)攻击中都可以使用该节。
    另外,命令行参数也保持在该区域中。
坚持原创技术分享,您的支持奖鼓励我继续创作!