第二章 存储管理 几个重要的数据结构和函数

 

 

 

 

struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)函数:

功能:给定一个属于某个进程的虚拟地址,要求找到其所属的区间以及相应的vma_area_struct结构;所找到的区间只要满足结束地址大于虚拟地址addr即可

参数:具体的哪个进程mm_struct下;虚拟地址

流程:先验证mm_struct中的mmap_cache(最近访问区),若不符合再从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 mm_struct *mm, struct vm_area_struct *vmp)函数:

功能:将一个虚拟区间插入到一个进程mm_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_area_struct数据结构中,第二把代表着整个虚存空间mm_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\n");
  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:  }

转载于:https://my.oschina.net/u/178323/blog/50597

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值