昨天将 VMA结构检视了一遍,也大概了解vma_area_struct
与 mm_struct
所包含的资料,那麽实际上会如何操作VMA呢?
首先要先了解,VMA 本身代表行程位址空间中的区间, VMA是有属性,也就是该段资料可以做什麽样的操作。 vm_flag
就是负责描述这些属性的, 这个标志记录了这个属性。 下列列出几个常见的 vm_flag
VM_READ
: 代表VMA可读取。
VM_WRITW
: 代表VMA可写入。
VM_EXEC
: 代表VMA可执行。
VM_SHARED
: 代表VMA允许多个行程共享。
VMA的属性可以任意组合,但是最终仍要在硬体机制上时线,并且记录在分页表里面的资料中。 在创建新的VMA时,可以用 vm_get_page_prot()
把 vm_flag
转成具体的分页表上的标记。
<mm/mmap.c>
pgprot_t vm_get_page_prot(unsigned long vm_flags){
pgprot_t ret = __pgprot(pgprot_val(protection_map[vm_flags \
& (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]));
return ret;
}
当CPU 发出了一个虚拟位址,该如何确定这个位址是否已经分配了VMA呢? Kernel 提供了一个API进行 VMA的查询。
<mm/mmap.c>
struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
struct vm_area_struct *find_vma_prev(struct mm_struct *mm, unsigned long addr,
struct vm_area_struct **pprev);
static inline struct vm_area_struct *find_vma_intersection(struct mm_struct * mm,
unsigned long start_addr, unsigned long end_addr)
find_vma()
可以根据给定的 addr
查找满足以下条件之一的 VMA,查找的目标如下
addr
在该VMA的空间范围内, 也就是 vma->vm_start
<= addr
<= vma->vm_end
addr
最近且结束地址大於 addr
的VMA。如果两个条件都不满足,会返回 NULL
,如果满足条件二, addr
不包含在该VMA内。
find_vma_intersection()
用来找出与 start_addr
或 end_addr
有交叠的 VMA,此函数可使用 find_vma()
完成; find_vma_prev()
则是找回前继的成员。
insert_vm_struct()
是kernel 提供的插入VMA的API // 这里有 __insert_vm_struct() 跟 insert_vm_struct() 有什麽差别? 还是根本没差
int insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vma)
{
struct vm_area_struct *prev;
struct rb_node **rb_link, *rb_parent;
if (find_vma_links(mm, vma->vm_start, vma->vm_end,
&prev, &rb_link, &rb_parent))
return -ENOMEM;
if ((vma->vm_flags & VM_ACCOUNT) &&
security_vm_enough_memory_mm(mm, vma_pages(vma)))
return -ENOMEM;
if (vma_is_anonymous(vma)) {
BUG_ON(vma->anon_vma);
vma->vm_pgoff = vma->vm_start >> PAGE_SHIFT;
}
vma_link(mm, vma, prev, rb_link, rb_parent);
return 0;
}
第6行 find_vma_links()
查找实际要插入的位置。
第12行 vma_is_anonymous()
判断是否是匿名映射的VMA
第17行 vma_link
将VMA插入链表以及红黑树中。
在新的VMA被加入行程的地址空间时,会检查是否可以与目前现存的VMA合并, vma_merge()
会用来将一个VMA跟附近的VMA合并。
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,
struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
在些参数之中 mm
是相关行程的 mm_struct
数据结构, prev
是新VMA前继的VMA节点, addr
与 end
代表新VMA的起始地址与结束地址, vm_flags
代表新VMA的标记。 如果新VMA是文件映射,参数file
会指向file数据结构。 proff
指定文件映射的偏移量 。 anon_vma
是匿名映射的数据结构。
"__" underscore 在同一个档案内 仍然算是不同的function, __ 的目的?
代表private for developer 不希望programer使用
另一些解法
https://stackoverflow.com/questions/10687053/meaning-of-double-underscore-in-the-beginning/10687114
https://hackmd.io/@VIRqdo35SvekIiH4p76B7g/BJ1kBwKo?type=view
https://b8807053.pixnet.net/blog/post/3612001
<<: Day30. Blue Prism本届最终章 –BP幕後花絮
原先的网站表现分数只有 74分 更换图片格式後网站表现分数 97分 可以看见最大内容绘制 LCP(L...
Web API 测试可以是後端工程师使用测试框架撰写白箱测试,也可以是 QA 使用测试工具进行黑箱测...
若有无法执行,请讯息或留言。 感谢你让我有修正的机会 :) Angular 1. Visual St...
物件导向的封装特性 封装特性:在一个物件产生之後,物件的部分成员属性和成员方法在逻辑上是不允许在物件...
前述 今天因为时间不足 T_T .... 所以教大家使用 qrcode.react ,可以很快速的产...