内存布局:应用程序是如何安排数据的

256 阅读2分钟

一个程序的机器码会被组织到同一个地方,这个地方就是代码段。

数据段存放的是程序中已经初始化且不为 0 的全局变量和静态变量。

对于未初始化的全局变量和静态变量,因为编译器知道它们的初始值都是 0,因此便不需要再在程序的二进制映像中存放这么多 0 了,只需要记录他们的大小即可,这便是 BSS 段。

与代码段以及数据段不同的是,堆和栈并不是从磁盘中加载,它们都是由程序在运行的过程中申请,在程序运行结束后释放。

image.png

除了上面所讲的基本内存区域外,现代应用程序中还会包含其他的一些内存区域,主要有以下几类:

  • 存放加载的共享库的内存空间:如果一个进程依赖共享库,那对应的,该共享库的代码段、数据段、BSS 段也需要被加载到这个进程的地址空间中。
  • 共享内存段:我们可以通过系统调用映射一块匿名区域作为共享内存,用来进行进程间通信。
  • 内存映射文件:我们也可以将磁盘的文件映射到内存中,用来进行文件编辑或者是类似共享内存的方式进行进程通信。

Section 主要是指在磁盘中的程序段,而 Segment 则用来指代内存中的程序段,Segment 是将具有相同权限属性的 Section 集合在一起,系统为它们分配的一块内存空间。

32位虚拟内存布局:

image.png

每次在进程向内核申请新的堆地址时候,其地址的值是在增大的。

每次进程申请新的栈地址时,其地址值是在减少的。

64位虚拟内存布局:

image.png

低 128T 的空间划分为用户空间,高 128T 划分为内核空间。

代码段跟数据段的中间还有一段不可以读写的保护段,它的作用也是防止程序在读写数据段的时候越界访问到代码段,这个保护段可以让越界访问行为直接崩溃,防止它继续往下运行。

不管是 32 位系统还是 64 位系统,内核都会维护一个变量 brk,指向堆的顶部,所以,brk 的位置实际上就决定了堆的大小。

根据映射的类型,mmap 有四种最常用的组合:

image.png

此文章为7月Day3学习笔记,内容来源于极客时间《编程高手必学的内存知识》