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

 

 

 

 

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

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

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

流程:先验证mm_struct中的mmap_cache(最近访问区),若不符合再从AVL树开始搜索,若没有AVL树则从mmap线性队列开始数据结构

源码:app

 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中去ui

参数:所要插入的mm_struct;虚拟区间atom

源码:spa

 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: }
相关文章
相关标签/搜索