简单的笔记下mmap.c中的部分函数:
find_vma:
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ /* 在mm中查找addr对应的线性地址块wma */ struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) { struct vm_area_struct *vma = NULL; /* mm不能为空,没什么好说的 */ if (mm) { /* Check the cache first. */ /* (Cache hit rate is typically around 35%.) */ /* mmap_cache保存的是上次访问该函数时返回的wma,一般来说,查找addr对应的wma时, addr一般都是累加的,因此有很大可能进行查找时,上次查找的就符合条件。 */ vma = mm->mmap_cache; /* 如果上次查找的wma不为空,而且addr恰好也在该wma之内,直接返回就OK了 */ if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { /* 如果上次查找的wma不符合条件,那就只能从mm中查找了。这里wma的存储是使用 红黑树来实现的,因此这里使用红黑树查找。 */ struct rb_node * rb_node; rb_node = mm->mm_rb.rb_node; vma = NULL; while (rb_node) { struct vm_area_struct * vma_tmp; vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); if (vma_tmp->vm_end > addr) { vma = vma_tmp; if (vma_tmp->vm_start <= addr) break; rb_node = rb_node->rb_left; } else rb_node = rb_node->rb_right; } /* 如果找到了,就存下来,加速后面的查找 */ if (vma) mm->mmap_cache = vma; } } return vma; } EXPORT_SYMBOL(find_vma); /* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ /* 在mm中查找addr对应的线性地址块wma,,不过同样也会返回该wma前面的那个wma */ struct vm_area_struct * find_vma_prev(struct mm_struct *mm, unsigned long addr, struct vm_area_struct **pprev) { struct vm_area_struct *vma = NULL, *prev = NULL; struct rb_node * rb_node; if (!mm) goto out; /* Guard against addr being lower than the first VMA */ vma = mm->mmap; /* Go through the RB tree quickly. */ rb_node = mm->mm_rb.rb_node; while (rb_node) { struct vm_area_struct *vma_tmp; vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); if (addr < vma_tmp->vm_end) { rb_node = rb_node->rb_left; } else { prev = vma_tmp; if (!prev->vm_next || (addr < prev->vm_next->vm_end)) break; rb_node = rb_node->rb_right; } } out: *pprev = prev; return prev ? prev->vm_next : vma; }
发表评论