第二章はいくつかの重要なデータ構造と関数を管理します.
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(¤t->mm->page_table_lock);
5: __insert_vm_struct(mm, vmp);
6: spin_unlock(¤t->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: }