1、进程地址空间概述
- 进程地址空间(process address space)是指进程可寻址的虚拟地址空间。
- 在64位的处理器中,进程可以寻址256TB的用户态地址空间,但是进程没权限去寻址内核空间的虚拟地址,只能通过系统调用的方式间接访问。而用户空间的进程地址空间则和可以被合法访问,地址空间称为内存区域(memory area)。
- 进程可以通过内核的内存管理机制动态地添加和删除这些内存区域,这些内存区域在Linux内核采用VMA数据结构来抽象描述。
- 每个内存区域具有相关的权限,如可读、可写或者可执行权限。若一个进程访问了不在有效范围的内存区域,或者非法访问了内存区域,或者以不正确的方式访问了内存区域,那么处理器会报告缺页异常。在Linux内核的缺页异常处理中会处理这些情况,严重的会报告Sement Fault,并终止该进程。
进程地址空间 - 内存区域
- 代码段映射,可执行文件中包含只读并可执行的程序头,如代码段和init段等。
- 数据段映射,可执行文件中包含可读/可写的程序头,如数据段和未初始化数据段等。
- 用户进程栈,通常位于用户空间的最高地址,从上往下延申。
- 它包含栈帧,里边包含局部变量和函数调用参数等。
- 注不要和内核栈混淆,进程的内核栈独立存在并由内核维护,主要用于上下文切换
- mmap区域,位于用户栈下面,主要用于mmap系统调用,如映射一个文件的内容到进程地址空间等。
- 堆区域,malloc函数分配的进程虚拟地址就是这段区域。
- 进程地址空间里的每个区域相互不重叠。
- 进程地址空间分配的虚拟地址一样,也不会内存区域重叠
- 进程地址空间是每个进程可以寻址的虚拟地址空间,每个进程在执行时都仿佛拥有了整个CPU内存资源。
64位Linux虚拟内存空间整体布局

2、mm_struct 数据结构
struct mm_struct {
struct vm_area_struct *mmap;
struct rb_root mm_rb;
unsigned long (*get_unmapped_area) (struct file *filp,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags);
unsigned long mmap_base;
pgd_t *pgd;
atomic_t mm_users;
int map_count;
atomic_t mm_count;
spinlock_t page_table_lock;
struct rw_semaphore mmap_sem;
struct list_head mmlist;
unsigned long total_vm;
unsigned long start_code,end_code,start_data,end_data;
unsigned long start_brk, brk, start_stack;
...
};
- 首先每个进程有一个进程控制块即 task_struct 结构体,来完整描述一个进程的所有信息,在加载程序的时,内核会创建task_struct结构体,
- 然后每个独立的进程都有自己的虚拟空间即 mm成员指向的mm_struct数据结构。
- task_struct 结构体包含一个mm_struct 结构体成员,
- mm_struct结构体包含一个vm_area_struct结构体成员mmap,
- 然后mmap成员指向一个VMA链表,管理所有VMA。
