第二章はいくつかの重要なデータ構造と関数を管理します.

10712 ワード


 
 
 
struct vm_アーアアウstruct*find_vma関数:
機能:あるプロセスに属する仮想アドレスを指定します.所属区間と対応するvma_を見つける必要があります.アーアアウstruct構造見つかった区間は、終了アドレスが仮想アドレスaddrより大きい場合に限ります.
パラメータ:具体的にどのプロセスがmm_ですか?structの下仮想アドレス
フロー:まずmm_を検証する.structの中のmmapcache(最近の訪問エリア)は、AVLツリーから検索を開始します.AVLツリーがないとmmapラインから開始します.
ソース:
   1:  /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
   2:  struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
   3:  {
   4:      struct vm_area_struct *vma = NULL;
   5:   
   6:      if (mm) {
   7:          /* Check the cache first. */
   8:          /* (Cache hit rate is typically around 35%.) */
   9:          vma = mm->mmap_cache;//       vma_area_struct    
  10:          if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {//        vma_area_struct ,  AVL          
  11:              if (!mm->mmap_avl) {
  12:                  /* Go through the linear list. */
  13:                  vma = mm->mmap;//      ,                  
  14:                  while (vma && vma->vm_end <= addr)
  15:                      vma = vma->vm_next;
  16:              } else {
  17:                  /* Then go through the AVL tree quickly. */
  18:                  struct vm_area_struct * tree = mm->mmap_avl;
  19:                  vma = NULL;
  20:                  for (;;) {
  21:                      if (tree == vm_avl_empty)
  22:                          break;
  23:                      if (tree->vm_end > addr) {
  24:                          vma = tree;
  25:                          if (tree->vm_start <= addr)
  26:                              break;
  27:                          tree = tree->vm_avl_left;
  28:                      } else
  29:                          tree = tree->vm_avl_right;
  30:                  }
  31:              }
  32:              if (vma)
  33:                  mm->mmap_cache = vma;//  mm_struct  mmap_cache         
  34:          }
  35:      }
  36:      return vma;
  37:  }
 
void insert_vm_struct(struct mmustruct*mm、struct vmuats*vmp)関数:
機能:一つの仮想区間を一つのプロセスに挿入します.struct中に行く
パラメータ:挿入するmm_struct;仮想区間
ソース:
   1:  void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp)
   2:  {
   3:      lock_vma_mappings(vmp);
   4:      spin_lock(&current->mm->page_table_lock);
   5:      __insert_vm_struct(mm, vmp);
   6:      spin_unlock(&current->mm->page_table_lock);
   7:      unlock_vma_mappings(vmp);
   8:  }
挿入操作中はいかなる干渉も許されません.二つのロックをかけました.第一弾は新しい区間のvm_を表します.アーアアウstructデータ構造の中で、第二は虚存空間全体を表しています.structデータ構造は、他のプロセスが途中で挿入できることを許さない.
   1:  /* Insert vm structure into process list sorted by address
   2:   * and into the inode's i_mmap ring.  If vm_file is non-NULL
   3:   * then the i_shared_lock must be held here.
   4:   */
   5:  void __insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp)
   6:  {
   7:      struct vm_area_struct **pprev;
   8:      struct file * file;
   9:   
  10:      if (!mm->mmap_avl) {//   AVL ,                      mm->mmap  
  11:          pprev = &mm->mmap;
  12:          while (*pprev && (*pprev)->vm_start <= vmp->vm_start)
  13:              pprev = &(*pprev)->vm_next;
  14:      } else {// AVL ,       AVL     ,    liner que
  15:          struct vm_area_struct *prev, *next;
  16:          avl_insert_neighbours(vmp, &mm->mmap_avl, &prev, &next);
  17:          pprev = (prev ? &prev->vm_next : &mm->mmap);
  18:          if (*pprev != next)
  19:              printk("insert_vm_struct: tree inconsistent with list
"
);
  20:      }
  21:      vmp->vm_next = *pprev;
  22:      *pprev = vmp;
  23:   
  24:      mm->map_count++; //vvm   1
  25:      if (mm->map_count >= AVL_MIN_MAP_COUNT && !mm->mmap_avl)//    mm_struct  ,  vvm    AVL_MIN_MAP_COUNT,    AVL 
  26:          build_mmap_avl(mm);
  27:   
  28:      file = vmp->vm_file;
  29:      if (file) {//            ,      :
  30:          struct inode * inode = file->f_dentry->d_inode;
  31:          struct address_space *mapping = inode->i_mapping;
  32:          struct vm_area_struct **head;
  33:   
  34:          if (vmp->vm_flags & VM_DENYWRITE)
  35:              atomic_dec(&inode->i_writecount);
  36:   
  37:          head = &mapping->i_mmap;
  38:          if (vmp->vm_flags & VM_SHARED)
  39:              head = &mapping->i_mmap_shared;
  40:        
  41:          /* insert vmp into inode's share list */
  42:          if((vmp->vm_next_share = *head) != NULL)
  43:              (*head)->vm_pprev_share = &vmp->vm_next_share;
  44:          *head = vmp;
  45:          vmp->vm_pprev_share = head;
  46:      }
  47:  }