Linux进程地址空间--vma的基本操作


在32位的系统上,线性地址空间可达到4GB,这4GB一般按照3:1的比例进行分配,也就是说用户进程享有前3GB线性地址空间,而内核独享最后1GB线性地址空间。由于虚拟内存的引入,每个进程都可拥有3GB的虚拟内存,并且用户进程之间的地址空间是互不可见、互不影响的,也就是说即使两个进程对同一个地址进行操作,也不会产生问题。在前面介绍的一些分配内存的途径中,无论是伙伴系统中分配页的函数,还是slab分配器中分配对象的函数,它们都会尽量快速地响应内核的分配请求,将相应的内存提交给内核使用,而内核对待用户空间显然不能如此。用户空间动态申请内存时往往只是获得一块线性地址的使用权,而并没有将这块线性地址区域与实际的物理内存对应上,只有当用户空间真正操作申请的内存时,才会触发一次缺页异常,这时内核才会分配实际的物理内存给用户空间。

用户进程的虚拟地址空间包含了若干区域,这些区域的分布方式是特定于体系结构的,不过所有的方式都包含下列成分:

可执行文件的二进制代码,也就是程序的代码段

存储全局变量的数据段

用于保存局部变量和实现函数调用的栈

环境变量和命令行参数

程序使用的动态库的代码

用于映射文件内容的区域

由此可以看到进程的虚拟内存空间会被分成不同的若干区域,每个区域都有其相关的属性和用途,一个合法的地址总是落在某个区域当中的,这些区域也不会重叠。在linux内核中,这样的区域被称之为虚拟内存区域(virtual memory areas),简称vma。一个vma就是一块连续的线性地址空间的抽象,它拥有自身的权限(可读,可写,可执行等等) ,每一个虚拟内存区域都由一个相关的struct vm_area_struct结构来描述

  1. struct vm_area_struct {  
  2.     struct mm_struct * vm_mm;   /* 所属的内存描述符 */  
  3.     unsigned long vm_start;    /* vma的起始地址 */  
  4.     unsigned long vm_end;       /* vma的结束地址 */  
  5.   
  6.     /* 该vma的在一个进程的vma链表中的前驱vma和后驱vma指针,链表中的vma都是按地址来排序的*/  
  7.     struct vm_area_struct *vm_next, *vm_prev;  
  8.   
  9.     pgprot_t vm_page_prot;      /* vma的访问权限 */  
  10.     unsigned long vm_flags;    /* 标识集 */  
  11.   
  12.     struct rb_node vm_rb;      /* 红黑树中对应的节点 */  
  13.   
  14.     /* 
  15.      * For areas with an address space and backing store, 
  16.      * linkage into the address_space->i_mmap prio tree, or 
  17.      * linkage to the list of like vmas hanging off its node, or 
  18.      * linkage of vma in the address_space->i_mmap_nonlinear list. 
  19.      */  
  20.     /* shared联合体用于和address space关联 */  
  21.     union {  
  22.         struct {  
  23.             struct list_head list;/* 用于链入非线性映射的链表 */  
  24.             void *parent;   /* aligns with prio_tree_node parent */  
  25.             struct vm_area_struct *head;  
  26.         } vm_set;  
  27.   
  28.         struct raw_prio_tree_node prio_tree_node;/*线性映射则链入i_mmap优先树*/  
  29.     } shared;  
  30.   
  31.     /* 
  32.      * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma 
  33.      * list, after a COW of one of the file pages.  A MAP_SHARED vma 
  34.      * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack 
  35.      * or brk vma (with NULL file) can only be in an anon_vma list. 
  36.      */  
  37.     /*anno_vma_node和annon_vma用于管理源自匿名映射的共享页*/  
  38.     struct list_head anon_vma_node; /* Serialized by anon_vma->lock */  
  39.     struct anon_vma *anon_vma;  /* Serialized by page_table_lock */  
  40.   
  41.     /* Function pointers to deal with this struct. */  
  42.     /*该vma上的各种标准操作函数指针集*/  
  43.     const struct vm_operations_struct *vm_ops;  
  44.   
  45.     /* Information about our backing store: */  
  46.     unsigned long vm_pgoff;     /* 映射文件的偏移量,以PAGE_SIZE为单位 */  
  47.     struct file * vm_file;          /* 映射的文件,没有则为NULL */  
  48.     void * vm_private_data;     /* was vm_pte (shared mem) */  
  49.     unsigned long vm_truncate_count;/* truncate_count or restart_addr */  
  50.   
  51. #ifndef CONFIG_MMU   
  52.     struct vm_region *vm_region;    /* NOMMU mapping region */  
  53. #endif   
  54. #ifdef CONFIG_NUMA   
  55.     struct mempolicy *vm_policy;    /* NUMA policy for the VMA */  
  56. #endif   
  57. };  
  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容