Linux下的进程内存结构
虚拟内存管理
Linux操作系统采用虚拟内存管理技术,使得每个进程都有独立的地址空间,该地址空间大小为4GB的线性虚拟空间,用户所看到和接触到的都是该虚拟地址,无法看到实际的物理内存地址。利用这种虚拟地址不但更安全(用户不能直接访问物理内存),而且用户程序可以使用比实际物理内存更大的地址空间。
虚拟空间
4GB的进程地址空间会被分成两部分———用户空间和内核空间。用户地址空间是0~3GB(0xC0000000),内核地址空间占据 3~4GB,用户进程在通常情况下只能访问用户空间虚拟地址,不能访问内核空间的虚拟地址,只有用户进程使用系统调用(代表用户进程在内核态执行)时才会访问到内核空间。每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它不会跟着变化,是固定的。内核空间地址有自己对应的页表,用户进程有着各自不同的页表,每个进程的用户空间都是完全独立的,互不相干。进程的虚拟内存地址空间如图(进程地空间的分布)。
内核虚拟内存 |
---|
堆栈 |
↓ |
Linux动态链接器 |
共享库的内存映射区域 |
↑ |
堆 |
数据段(.data、.bss) |
只读段(.init、.text、.rodata) |
段
用户空间包括以下几个功能区域(通常称为“段”)
- 只读段 ,具有只读属性,包含程序代码(.init和.text)和只读数据(.rodata);
- 数据段,存放的是全局变量和静态变量,其中初始化数据段存放在显示初始化的全局变量和静态变量,未初始化数据段,此段通常被称为BBS段,存放未进行显示初始化的全局变量和静态变量。
- 栈,由系统自动分配释放,存放函数的参数值、局部变量的值、返回地址等。
- 堆存放动态分配的数据,一般由程序员动态分配和释放,若程序员不释放,程序结束可能由系统自动回收。
- 共享库的内存映射区域,这是Linux动态链接器和其他共享库代码的映射区域。
因为在Linux系统每个进程都会有“/proc”文件系统下的与之对应的一个目录,例如init进程相关信息存放在“/proc/1”目录下。因此可以通过proc文件系统查看某个进程的地址空间的映射情况。