进程地址空间分布图
![Linux程序内存布局图.png](https://i.loli.net/2020/08/05/jxbWsi5ae4q1GfR.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 | 只读文本段中的程序代码段 | 程序的代码 |
参考
-
《UNIX环境高级编程》