linux进程参数地址,Linux进程地址空间--vma的基本操作

void vma_adjust(struct vm_area_struct *vma, unsigned long start,

unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert)

{

struct mm_struct *mm = vma->vm_mm;

struct vm_area_struct *next = vma->vm_next;

struct vm_area_struct *importer = NULL;

struct address_space *mapping = NULL;

struct prio_tree_root *root = NULL;

struct file *file = vma->vm_file;

struct anon_vma *anon_vma = NULL;

long adjust_next = 0;

int remove_next = 0;

if (next && !insert) {

/*指定的范围已经跨越了整个后驱vma,并且有可能超过后驱vma*/

if (end >= next->vm_end) {

/*

* vma expands, overlapping all the next, and

* perhaps the one after too (mprotect case 6).

*/

again:          remove_next = 1 + (end > next->vm_end);//确定是否超过了后驱vma

end = next->vm_end;

anon_vma = next->anon_vma;

importer = vma;

} else if (end > next->vm_start) {/*指定的区域和后驱vma部分重合*/

/*

* vma expands, overlapping part of the next:

* mprotect case 5 shifting the boundary up.

*/

adjust_next = (end - next->vm_start) >> PAGE_SHIFT;

anon_vma = next->anon_vma;

importer = vma;

} else if (end vm_end) {/*指定的区域没到达后驱vma的结束处*/

/*

* vma shrinks, and !insert tells it's not

* split_vma inserting another: so it must be

* mprotect case 4 shifting the boundary down.

*/

adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);

anon_vma = next->anon_vma;

importer = next;

}

}

if (file) {//如果有映射文件

mapping = file->f_mapping;//获取文件对应的address_space

if (!(vma->vm_flags & VM_NONLINEAR))

root = &mapping->i_mmap;

spin_lock(&mapping->i_mmap_lock);

if (importer &&

vma->vm_truncate_count != next->vm_truncate_count) {

/*

* unmap_mapping_range might be in progress:

* ensure that the expanding vma is rescanned.

*/

importer->vm_truncate_count = 0;

}

/*如果指定了待插入的vma,则根据vma是否以非线性的方式映射文件来选择是将

vma插入file对应的address_space的优先树(对应线性映射)还是双向链表(非线性映射)*/

if (insert) {

insert->vm_truncate_count = vma->vm_truncate_count;

/*

* Put into prio_tree now, so instantiated pages

* are visible to arm/parisc __flush_dcache_page

* throughout; but we cannot insert into address

* space until vma start or end is updated.

*/

__vma_link_file(insert);

}

}

/*

* When changing only vma->vm_end, we don't really need

* anon_vma lock.

*/

if (vma->anon_vma && (insert || importer || start != vma->vm_start))

anon_vma = vma->anon_vma;

if (anon_vma) {

spin_lock(&anon_vma->lock);

/*

* Easily overlooked: when mprotect shifts the boundary,

* make sure the expanding vma has anon_vma set if the

* shrinking vma had, to cover any anon pages imported.

*/

if (importer && !importer->anon_vma) {

importer->anon_vma = anon_vma;

__anon_vma_link(importer);//将importer插入importer的anon_vma匿名映射链表中

}

}

if (root) {

flush_dcache_mmap_lock(mapping);

vma_prio_tree_remove(vma, root);

if (adjust_next)

vma_prio_tree_remove(next, root);

}

/*调整vma的相关量*/

vma->vm_start = start;

vma->vm_end = end;

vma->vm_pgoff = pgoff;

if (adjust_next) {//调整后驱vma的相关量

next->vm_start += adjust_next <

next->vm_pgoff += adjust_next;

}

if (root) {

if (adjust_next)//如果后驱vma被调整了,则重新插入到优先树中

vma_prio_tree_insert(next, root);

vma_prio_tree_insert(vma, root);//将vma插入到优先树中

flush_dcache_mmap_unlock(mapping);

}

if (remove_next) {//给定区域与后驱vma有重合

/*

* vma_merge has merged next into vma, and needs

* us to remove next before dropping the locks.

*/

__vma_unlink(mm, next, vma);//将后驱vma从红黑树中删除

if (file)//将后驱vma从文件对应的address space中删除

__remove_shared_vm_struct(next, file, mapping);

if (next->anon_vma)//将后驱vma从匿名映射链表中删除

__anon_vma_merge(vma, next);

} else if (insert) {

/*

* split_vma has split insert from vma, and needs

* us to insert it before dropping the locks

* (it may either follow vma or precede it).

*/

__insert_vm_struct(mm, insert);//将待插入的vma插入mm的红黑树,双向链表以及

//匿名映射链表

}

if (anon_vma)

spin_unlock(&anon_vma->lock);

if (mapping)

spin_unlock(&mapping->i_mmap_lock);

if (remove_next) {

if (file) {

fput(file);

if (next->vm_flags & VM_EXECUTABLE)

removed_exe_file_vma(mm);

}

mm->map_count--;

mpol_put(vma_policy(next));

kmem_cache_free(vm_area_cachep, next);

/*

* In mprotect's case 6 (see comments on vma_merge),

* we must remove another next too. It would clutter

* up the code too much to do both in one go.

*/

if (remove_next == 2) {//还有待删除的区域

next = vma->vm_next;

goto again;

}

}

validate_mm(mm);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值