第二章 存儲管理 幾個重要的數據結構和函數

 

 

 

 

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: }
相關文章
相關標籤/搜索