拆分
拆分页表
现在的透明大页还支持拆分,这样可以在必要的时候退回到四级页表。
这个工作由函数__split_huge_pmd_locked完成。
__split_huge_pmd_locked
pgtable = pgtable_trans_huge_withdraw(mm, pmd);
pmd_populate(mm, &_pmd, pgtable);
for (i = 0; i < HPAGE_PMD_NR; i++) {
set_pte_at(mm, addr, pte, entry);
}
pmd_populate(mm, pmd, pgtable);
其实说白了很简单,就是把预留了页表拿出来,每一项都填上大页对应的地址。最后把相应的pmd改好。是不是有点酷。
当然我这个流程中只显示了匿名页的拆分过程,对于文件页还需要继续学习。
拆分大页
拆分页表最终的目的也是为了拆分大页,这样在系统内存不够时可以回收大页中没有使用的部分。
下图是一个非常简化版本的大致流程。
split_huge_page_to_list
unmap_page
try_to_unmap_one
...
__split_huge_pmd_locked
__split_huge_page
remap_page
可以看到,拆分大页的过程中,也有可能会拆分页表。此时我们称之为PMD-mapped THP。如果这个大页的页表已经被拆分过了,就不需要也不能再次拆分,我们就叫它PTE-mapped THP。
所以对于匿名大页,整个拆分的过程就分成两种情况
PMD-mapped THP
PTE-mapped THP
我们分别来看看这两种情况下拆分过程中细微的差别。
对于PMD-mapped THP, __split_huge_pmd_locked函数会执行到。该函数会将PTE entry改写成migration entry。然后在函数remap_page中再将migration entry 恢复到页表中。怎么样,是不是很有意思。
对于PTE-mapped THP, __split_huge_pmd_locked函数不会被执行,因为页表早已拆分。此时try_to_unmap_one函数就担负起将PTE entry设置成migration entry的重任。接下来就和之前一样,由remap_page将migration entry恢复到页表中。
Last updated
Was this helpful?