Linux内存空间布局
- .text:一般最开始的segment是代码段,包含了ELF可执行程序的代码指令,内存属性为可读可执行(不可写)
- .data:数据段一般在代码段的后面,包含了ELF可执行程序的已经初始化的变量。
- .bss:未初始化数据段一般是最后一个段,包含了未初始化的全局变量和静态变量。(这里需要注意一点的是初始化为0的全局变量和静态变量也是会放在.bss段的)
- heap是堆内存,所有程序动态申请的内存都在此内存范围内,在程序编译时会设置默认堆内存的大小,如果在使用的时候不够用就会往高地址增长。
- mapping共享内存区域,包含了内存映射文件,动态链接库等,可以向底和高地址扩展。
- stack是栈内存,在程序编译时会设置栈内存的大小,但是实际分配物理内存的一开始只有一个页面大小,然后程序运行中栈内存往低地址增长,最大增长到默认的栈内存大小。
进程控制块task_struct
操作系统为了管理多个进程会通过进程控制块PCB来保存进程的运行时信息。
Linux中的PCB就是task_struct,其中mm_struct为进程内存描述符(用于描述0-3G用户内存空间)
struct task_struct {
struct mm_struct *mm; //指向进程内存描述符
pid_t pid; //进程pid
......
}
进程内存描述符mm_struct
- 进程内存描述符用来描述程序0-3G用户内存空间的内存信息
- vm_area_struct是用户内存块的线性内存描述符(相当于windows中的VAD),对应内核空间中有vm_struct表示内核空间内存块的线性内存描述符。
- 当用户进程内存块较少时,mmap指向内存块的线性内存描述符链表
- 当用户进程内存块较多时,mm_rb是对应内存块的线性内存描述符红黑树的根结点(相当于windows中的VAD红黑树)
struct mm_struct {
struct {
struct vm_area_struct *mmap; //指向一条线性内存描述符vm_area_struct的链表
struct rb_root mm_rb; //为线性内存描述符红黑树Root的根结点
......
} __randomize_layout;
......
}
/proc/pid/mmaps
当我们查看某个进程的用户内存空间分布是会执行cat /proc/pid/mmaps
,这条指令查看mmaps文件中的内容其实就是对应的mm_struct.mmap或者mm_struct.mm_rb中的数据。