darling54454 发表于 2016-02-27 13:53

VMA合并函数,vma_merge

本帖最后由 darling54454 于 2016-02-27 13:54 编辑

先贴该函数主要代码:
struct vm_area_struct *vma_merge(struct mm_struct *mm, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *anon_vma, struct file *file, pgoff_t pgoff, struct mempolicy *policy)
{
        pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
        struct vm_area_struct *area, *next;


        if (vm_flags & VM_SPECIAL)
                return NULL;

        if (prev)
                next = prev->vm_next;
        else
                next = mm->mmap;
        area = next;
       //传递进来的参数,next->vm_end == end,这个条件怎么会成立呢。
       // addr 和 end ,应该都是通过申请得到的区间吧,不应该和其他VMA覆盖的。
        if (next && next->vm_end == end)                /* cases 6, 7, 8 */
                next = next->vm_next;

       //同前一个合并。
        if (prev && prev->vm_end == addr && mpol_equal(vma_policy(prev), policy) && can_vma_merge_after(prev, vm_flags,anon_vma, file, pgoff)) {

        }

       //同后一个合并。
        if (next && end == next->vm_start && mpol_equal(policy, vma_policy(next)) && can_vma_merge_before(next, vm_flags, anon_vma, file, pgoff+pglen)) {

        }

        return NULL;
}

Buddy_Zhang1 发表于 2016-02-27 16:00

addr 和 end 是通过申请获得,它可以和其他虚拟区重合,你可以做一下这方面的测试.

对于 "if (next && next->vm_end == end)                /* cases 6, 7, 8 */"

对于上面的 case 分别为:
case6:
新申请的 addr 为 prev->vm_end
新申请的 end   为 next->vm_end
但 next->vm_end == next->vm_next->vm_start;
case 7:
新申请的 addr 为 prev->vm_end
新申请的 end   为 next->vm_end
但 next->vm_end != next->vm_next->vm_start;
case 8:
新申请的 addr> prev->vm_end
新申请的 end   为 next->vm_end
但 next->vm_end == next->vm_next->vm_start;

darling54454 发表于 2016-02-28 14:58

回复 2# Buddy_Zhang1
你好。
如果说可以重叠话,那也挺困惑的。
假设addr = prev->end.
   end是在next的区间内部的(next-> start < end < next->end).

那么程序的执行就是:
struct vm_area_struct *vma_merge(............)
{
        pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
        struct vm_area_struct *area, *next;

        if (vm_flags & VM_SPECIAL)
                return NULL;

        if (prev)
                next = prev->vm_next;
        else
                next = mm->mmap;
        area = next;
        if (next && next->vm_end == end)                /* cases 6, 7, 8 */
                next = next->vm_next;

        if (prev && prev->vm_end == addr && mpol_equal(vma_policy(prev), policy) && can_vma_merge_after(prev, vm_flags, anon_vma, file, pgoff)) {

                if (next && end == next->vm_start &&mpol_equal(policy, vma_policy(next)) &&can_vma_merge_before(next, vm_flags, anon_vma, file, pgoff+pglen) && is_mergeable_anon_vma(prev->anon_vma, next->anon_vma)) {
                                                        /* cases 1, 6 */
                        vma_adjust(prev, prev->vm_start, next->vm_end, prev->vm_pgoff, NULL);
                } else                                        /* cases 2, 5, 7 */
                        vma_adjust(prev, prev->vm_start, end, prev->vm_pgoff, NULL);
                return prev;
        }
      ....
      ....

        return NULL;
}
程序中对A和要新添加的区域进行了调用can_vma_merge_after来判断属性是不是可以合并,假设可以合并。
在vma_adjust会对B区域进行分割。但是,并没有对新添加的区域和B进行判断属性。
可以允许这样的操作?

   

Buddy_Zhang1 发表于 2016-02-28 16:30

回复 3# darling54454

如果新的区和 next 区域重叠,那么就将 next 区 vma_split() 成两个区,next 区的前半部 merge 到新区内,next 区后半部区称为一个独立的新区.

   
页: [1]
查看完整版本: VMA合并函数,vma_merge