struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
用于根据属于某个进程的虚拟地址,找到其所属的进程虚拟区间,并返回相应的vm_area_struct 指针
其使用的例程如下:
static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long old_start = vma->vm_start;
unsigned long old_end = vma->vm_end;
unsigned long length = old_end - old_start;
unsigned long new_start = old_start - shift;
unsigned long new_end = old_end - shift;
struct mmu_gather tlb;
BUG_ON(new_start > new_end);
/*
* ensure there are no vmas between where we want to go
* and where we are
*/
if (vma != find_vma(mm, new_start))
return -EFAULT;
}
其源码分析如下:
struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
{
struct rb_node *rb_node;
struct vm_area_struct *vma;
/* Check the cache first. */
#首先查找addr释放在vma的cache中是否有缓存
vma = vmacache_find(mm, addr);
#这里用likely修饰,看来有很大的几率可以找到
if (likely(vma))
return vma;
#进程的虚拟空间是按红黑树组织的。如果在cache中没有找到的话,这里会遍历红黑树查找
rb_node = mm->mm_rb.rb_node;
while (rb_node) {
struct vm_area_struct *tmp;
tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb);
if (tmp->vm_end > addr) {
vma = tmp;
#查找到的标准是 tmp->vm_start < addr < tmp->vm_end.
if (tmp->vm_start <= addr)
break;
rb_node = rb_node->rb_left;
} else
rb_node = rb_node->rb_right;
}
#如果找到vma的话,则将这个vma更新到缓存中
if (vma)
vmacache_update(addr, vma);
return vma;
}
内存管理API之find_vma
最新推荐文章于 2024-08-04 18:48:14 发布