进程地址空间 find_vma()

来源:互联网 发布:分析家软件 编辑:程序博客网 时间:2024/06/06 00:13

进程地址空间 find_vma()

find_vma()功能是查找给定地址的最邻近区,是寻找合适的线性地址空间至关重要的函数。find_vma()函数有两个参数:进程内存描述符的地址mm和线性地址addr。查找线性区的vm_end字段大于addr的第一个线性区的位置,并返回这个线性区描述符的地址;如果没有这样的线性区存在,就返回-个NULL指针。
补充:
内核用两个数据结构表示进程地址空间: struct mm_struct(内存描述符) 和 struct vm_area_struct(线性区描述符) 表示。
struct mm_struct 记录进程地址空间有关的全部信息,进程描述符struct task_struct中mm字段指向属于自己的mm_struct(内存描述符)。
struct vm_area_struct 记录进程使用每个线性区以及线性区的属性。内核中用两种数据结构组织每个进程所使用的线性区—-链表和红黑树,这样做的好处是加快查找的速度。struct mm_struct中mmap 和 mm_rb字段分别存放其链表头和红黑树根结点。

/* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */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. */    vma = vmacache_find(mm, addr);    if (likely(vma))        return vma;    /* 查找第一个vm_end字段大于addr的线性区 */    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;            if (tmp->vm_start <= addr)                break;            rb_node = rb_node->rb_left;        } else            rb_node = rb_node->rb_right;    }/*  * vmacache_update : 将新得到的vma缓冲到struct task_struct中vmacache数组中, *                  提高下次查找的命中率. * 原因 : 程序中引用地址的局部性使下面这种情况出现的可能性很大,如果检查的最后一个 *        线性地址属于某一给定的线性区,那么下一个要前差的线性地址也属于这个线性区。 */    if (vma)        vmacache_update(addr, vma);    return vma;}EXPORT_SYMBOL(find_vma)
0 0