首页 > 技术文章 > Linux进程地址空间(程序内存布局)

jakelin 2021-01-25 13:48 原文

进程地址空间分布图

Linux程序内存布局图.png

由低地址到高地址,依次是:

  • 程序段(text):程序代码在内存中的映射,存放函数体的二进制代码,常常是只读的

  • 初始化过的数据(data):在程序运行初已经对变量进行初始化的数据

    • 只读数据段(RO data,即常量区):

      这个区域的存在与否,一直是一个争议的地方,但是我们这里认同是存在的,因为我们的程序中的确出现了与其他数据段不同的一块区域,但是往往很多时候大家把只读数据段(RO data)和下面的已初始化读写数据段(RW data)合成为数据段data,但是其实这个是不合适的,因为在执行过程中,这两个区域的读写权限是不同的,顾名思义,只读数据段(RO data)是只读的,而已初始化读写数据段是可读可写的。

    • 读写数据段(RW data):需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写

  • 未初始化过的数据(bss):未初始化数据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。Block Started by Symbol,BSS段的变量只有名称和大小却没有值

  • 堆 (heap):存储动态内存分配,需要程序员手工分配,手工释放。注意它与数据结构中的堆是两回事,分配方式类似于链表

  • 栈(stack):存储局部、临时变量,函数调用时,存储函数的返回指针,用于控制函数的调用和返回。在程序块开始时自动分配内存,结束时自动释放内存,其操作方式类似于数据结构中的栈

  • 内核空间(kernel)

内核空间

Linux的虚拟地址空间范围为0~4G,Linux内核将这4G字节的空间分为两部分:

内核空间:将高地址的1G字节供内核使用,称为“内核空间“

用户空间:低地址的3G字节(供各个进程使用,称为“用户空间“

因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享

Linux使用两级保护机制:

  • 0级供内核使用
  • 3级供用户程序使用

虚拟地址!!!

进程空间是虚拟地址,不管是内核空间还是用户空间,它们都处于虚拟空间中。

使用虚拟地址可以很好的保护内核空间被用户空间破坏,虚拟地址到物理地址转换过程由操作系统和CPU共同完成(操作系统为CPU设置好页表,CPU通过MMU单元进行地址转换)。

段区对应数据

进程空间段区域 地址空间 存储变量
stack 局部变量和常量
heap 动态分配的数据
BSS 未初始化数据段 未初始化的全局变量以及静态变量
RW data 已初始化读写数据段 已初始化的全局变量和静态变量
RO data 只读文本段中的数据段 全局常量或者字符串面变量
text 只读文本段中的程序代码段 程序的代码

参考

推荐阅读