
unsigned long mmap_base; /* base of mmap area */
unsigned long total_vm; /* total_vm 是总共映射的页的数目 */
unsigned long locked_vm; /* Pages that have PG_mlocked set */
unsigned long pinned_vm; /* Refcount permanently increased */
unsigned long data_vm; /* VM_WRITE & ~VM_SHARED & ~VM_STACK */
unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE & ~VM_STACK */
unsigned long stack_vm; /* VM_STACK */
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
total_vm 是总共映射的页的数目,内存吃紧的时候,locked_vm 就是被锁定不能换出,pinned_vm 是不能换出,也不能移动。 换出 : 把内存写到硬盘
data_vm 是存放数据的页的数目,exec_vm 是存放可执行文件的页的数目,stack_vm 是栈所占的页的数目。
start_code 和 end_code 表示可执行代码的开始和结束位置,start_data 和 end_data 表示已初始化数据的开始位置和结束位置。
start_brk 是堆的起始位置,brk 是堆当前的结束位置。前面咱们讲过 malloc 申请一小块内存的话,就是通过改变 brk 位置实现的。
start_stack 是栈的起始位置,栈的结束位置在寄存器的栈顶指针中。
arg_start 和 arg_end 是参数列表的位置, env_start 和 env_end 是环境变量的位置。它们都位于栈中最高地址的地方。
mmap_base 表示虚拟地址空间中用于内存映射的起始地址。这个空间是从高地址到低地址增长的。

这里用红黑树,就是为了快速查找一个内存区域,并在需要改变的时候,能够快速修改
anoy 就是 anonymous,匿名的意思,映射到文件就需要有 vm_file 指定被映射的文件。
当 exec 运行一个二进制程序的时候,除了解析 ELF 的格式之外,另外一个重要的事情就是建立内存映射。

内存映射图 :

下面这俩种情况都会修改上面的映射关系
第一种情况是函数的调用,涉及函数栈的改变,主要是改变栈顶指针。
第二种情况是通过 malloc 申请一个堆内的空间,当然底层要么执行 brk,要么执行 mmap。关于内存映射的部分。
brk (堆) : 堆是从低地址向高地址增长的, 会有新旧的brk堆顶地址, 需要比较,如果俩者相同的话,则说明在同一页,则修改堆顶地址就行,指向新的地址, 如果新的 < 旧的 则说明不在一页,至少需要释放一页。
32 位

64位


