几个关键的数据结构
一个进程的虚拟地址空间主要由两个数据结来描述,一个是 mm_struct,一个是 vm_area_structs。
mm_struct结构描述了一个进程的整个虚拟地址空间,vm_area_truct描述了虚拟地址空间的一个区间(简称虚拟区)。下图就是我们所说的由task_struct到mm_struct,进程的地址空间的分布。
每一个进程都会有自己独立的mm_struct,这样每一个进程都会有自己独立的地址空间,这样才能互不干扰。当进程之间的地址空间被共享的时候,我们可以理解为这个时候是多个进程使用一份地址空间,这就是线程。
- struct mm_struct
- {
- struct vm_area_struct *mmap; //指向虚拟区间(VMA)链表
- struct rb_root mm_rb; //指向red_black树
- struct vm_area_struct *mmap_cache; //找到最近的虚拟区间
-
- unsigned long(*get_unmapped_area)(struct file *filp,unsigned long addr,unsigned long len,unsigned long pgoof,unsigned long flags);
-
- void (*unmap_area)(struct mm_struct *mm,unsigned long addr);
-
- unsigned long mmap_base;
-
- unsigned long task_size; //拥有该结构体的进程的虚拟地址空间的大小
- unsigned long cached_hole_size;
- unsigned long free_area_cache;
-
- pgd_t *pgd; //指向页全局目录
-
- atomic_t mm_users; //用户空间中有多少用户
- atomic_t mm_count; //对"struct mm_struct"有多少引用
-
- int map_count; //虚拟区间的个数
- struct rw_semaphore mmap_sem;
- spinlock_t page_table_lock; //保护任务页表和mm->rss
-
- struct list_head mmlist; //所有活动mm的链表
- mm_counter_t _file_rss;
- mm_counter_t _anon_rss;
- unsigned long hiwter_rss;
- unsigned long hiwater_vm;
-
-
- unsigned long total_vm,locked_vm,shared_vm,exec_vm;
- usingned long stack_vm,reserved_vm,def_flags,nr_ptes;
-
- unsingned long start_code,end_code,start_data,end_data; //代码段的开始start_code ,结束end_code,数据段的开始start_data,结束end_data
-
- unsigned long start_brk,brk,start_stack; //start_brk和brk记录有关堆的信息,start_brk是用户虚拟地址空间初始化,brk是当前堆的结束地址,start_stack是栈的起始地址
-
- unsigned long arg_start,arg_end,env_start,env_end; //参数段的开始arg_start,结束arg_end,环境段的开始env_start,结束env_end
- unsigned long saved_auxv[AT_VECTOR_SIZE];
-
- struct linux_binfmt *binfmt;
-
- cpumask_t cpu_vm_mask;
- mm_counter_t context;
- unsigned int faultstamp;
- unsigned int token_priority;
- unsigned int last_interval;
-
- unsigned long flags;
- struct core_state *core_state;
- }
分配的每个虚拟内存区域都由一个vm_area_struct 数据结构来管理,包括虚拟内存的起始和结束地址,以及内存的访问权限等,通常命名为vma;vm_area_struct 数据结构的定义如下:
- struct vm_area_struct {
-
-
- unsigned long vm_start;
- unsigned long vm_end;
-
-
- struct vm_area_struct *vm_next, *vm_prev;
-
- struct rb_node vm_rb;
-
-
- unsigned long rb_subtree_gap;
-
-
-
- struct mm_struct *vm_mm;
- pgprot_t vm_page_prot;
- unsigned long vm_flags;
-
-
- union {
- struct {
- struct rb_node rb;
- unsigned long rb_subtree_last;
- } linear;
- struct list_head nonlinear;
- } shared;
-
-
- struct list_head anon_vma_chain;
- struct anon_vma *anon_vma;
-
-
- const struct vm_operations_struct *vm_ops;
-
-
- unsigned long vm_pgoff;
- struct file * vm_file;
- void * vm_private_data;
-
- #ifndef CONFIG_MMU
- struct vm_region *vm_region;
- #endif
- #ifdef CONFIG_NUMA
- struct mempolicy *vm_policy;
- #endif
- };
小实验
- insmod test.ko pid_mem=3253 显示各个vma区域
- cat /proc/3253/maps 显示各个vma区域
看下两种方式的对比: