博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第二章 存储管理 几个重要的数据结构和函数
阅读量:6431 次
发布时间:2019-06-23

本文共 4343 字,大约阅读时间需要 14 分钟。

hot3.png

 

 

 

 

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

你可能感兴趣的文章
Cg关键字(keywords)
查看>>
Linux/Unix编程中的线程安全问题【转】
查看>>
一个IT人的成长路
查看>>
Oracle]高效的SQL语句之分析函数
查看>>
vs2008 断点无效 解决方法
查看>>
语言的信息密度
查看>>
Android数字选择器-NumberPicker
查看>>
Android SDK Manager 更新失败的解决方法
查看>>
Java并发编程:volatile关键字解析
查看>>
Java实现分页数据获取CachedRowSet
查看>>
Lambda应用设计模式
查看>>
4.2. MuseScore
查看>>
Asp.net管道模型(管线模型)之一发不可收拾
查看>>
Silverlight 解谜游戏 之十七 胜利界面优化
查看>>
C#使用OleDB操作ACCESS插入数据时提示:参数 @p_Contract 没有默认值
查看>>
HTML基础8--CSS、滑动门
查看>>
Oracle Database 9i/10g安装后的基本环境与服务
查看>>
IBatis 简易框架搭建
查看>>
冰血暴第一季/全集Fargo迅雷下载
查看>>
c语言_文件操作_FILE结构体解释_涉及对操作系统文件FCB操作的解释_
查看>>