图来了:
实际操作一把:
cat /proc/pagetypeinfo如下图:
这个处理的过程还是很复杂的,下图显示了大概的过程:
下边将针对各个子模块更深入点分析。
compaction_suitable
判断是否执行内存的碎片整理,需要满足以下三个条件:
除去申请的页面,空闲页面数将低于水印值,或者虽然大于等于水印值,但是没有一个足够大的空闲页块;
空闲页面减去两倍的申请页面(两倍表明有足够多的的空闲页面作为迁移目标),高于水印值;
申请的order大于PAGE_ALLOC_COSTLY_ORDER时,计算碎片指数fragindex,根据值来判断;
isolate_migratepages
isolate_migratepages函数中,迁移扫描器以pageblock为单位,扫描可移动页,最终把可移动的页添加到struct compact_control结构中的migratepages链表中。如下图所示:
isolate_freepages的逻辑与isolate_migratepages类似,也是对页进行隔离处理,最终添加cc->freepages链表中。
当空闲扫描器和迁移扫描器完成扫描之后,那就是时候将两个链表中的页做一下migrate操作了。
migrate_pages
调用compact_alloc函数,从cc->freepages链表中取出一个空闲页;
调用__unmap_and_move来把可移动页移动到空闲页处;
_unmap_and_move函数涉及到反向映射,以及页缓存等,留在以后再深入看。这个函数两个关键作用:1)调用try_to_unmap删除进程页表中旧的映射关系,在需要访问的时候再重新映射到新的物理地址上;2)调用move_to_new_page函数将旧页移动到新的物理页上,其中在汇编文件arch/arm64/lib/copy_page.S中copy_page函数完成拷贝。
compact_finished
compact_finished函数主要用于检查compact是否完成。