主旨
运行进程需要将必须数据存放在内存上。为了安全高效使用物理内存,每个进程都使用自己的虚拟内存空间。
进程虚拟内存空间布局
cat或pmap看进程的虚拟内存空间布局
cat /proc/pid/maps
或
pmap pid
32位机器上进程虚拟空间的分布
32位机器的寻址范围是2^32,即4G。其中用户态空间3G、内核态空间1G。
进程的虚拟地址空间分布如图所示,其中从低地址到高地址依次是
- 保留区
- 0x00000000~0x08048000区域不可访问,因为在多数操作系统中,数值较小的地址不是合法的。C语言中将无效的指针置为NULL,即指向保留区。
- 代码段
- 程序编译好以后作为二进制文件放在硬盘上,运行之前加载进内存。程序二进制文件中的机器码放在代码段。
- 数据段
- 数据段是在代码中指定了初始值的全局变量和静态变量。
- bss段
- bss段是没有指定初始值的全局变量和静态变量,在加载入内存后会初始化为0
- 堆
- 堆存放的是程序运行中动态申请的内存,如malloc
- start_brk标志堆的起始地址,brk标志堆的结束地址。通过改变brk的位置实现动态改变内存分配
- 堆由低地址向高地址生长,堆上方有一段待分配区域
- 文件映射与匿名映射区
- 进程需要使用的文件映射到内存中这块区域
- 动态链接库的代码段、数据段、bss段
- 文件映射与匿名映射区从高地址向低地址生长
- 栈
- 存放调用函数过程使用到的局部变量和函数参数
- 栈向低地址生长,栈下方有一段待分配区域
- start_stack标志栈的起始地址,RSP寄存器保存栈顶指针,RBP寄存器保存栈基地址
64位机器上进程虚拟内存空间分布
64位机器上,指针的寻址空间是2^64,也即16EB。这个空间太大了,因此不会这样使用,而是只用48位来描述虚拟内存空间,也就是2^48,256TB。
低128T(0x0000 0000 0000 0000 ~ 0x0000 7FFF FFFF F000)表示用户态虚拟内存空间。