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;
}
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; 回复 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进行判断属性。
可以允许这样的操作?
回复 3# darling54454
如果新的区和 next 区域重叠,那么就将 next 区 vma_split() 成两个区,next 区的前半部 merge 到新区内,next 区后半部区称为一个独立的新区.
页:
[1]