KSM

Posted by Maggie on November 20, 2020

ksm 页面合并过程

  • 开始扫描:从ksm_mm_head(mm_slot链表)中的头部开始扫描, 遍历整个链表
    • 开始扫描的时候初始化一个“控制结构” ksm_scan,起始地址为0,ksm->rmap_list指向 mm_slot->rmap_list链表头部。
  • 对于一个mm_slot:该结构是 ksm机制中回收对应的结构体, 该结构体与mm_struct(也就是一个进程)一一对应。
    • 扫描整个 mm_struct的每个vma, 如果VMA可以合并, 进入VMA
  • 对于每一个mergable VMA,遍历每一个页面(匿名页面!),并在 mm_slot->rmap_list找到(没找到就分配)对应的rmap_item
  • 对于一个page, 进行下面的页面检查和合并过程 。并在将page加入到 stable-tree 和 unstable-tree过程中, 建立rmap_item和 相应的树之间的关系。

相关代码:

1
2
3
4
// 将page替换为 ksm page, 并建立反向映射,对于旧的page, 清除反向映射
replace_page
// 在VMA找到一个Page之后: 在stable-tree和unstable-tree中找可以合并的 KSM page的过程
cmp_and_merge_page

ksm数据流分析

页面检查和合并过程

  • 首先在stable-tree中查找
    • 如果该页面已经被添加到stable-tree中(通过page->flags判断,并通过page->mapping得到stable_node)
    • 如果该 物理页面还没有被添加到stable-tree中, 就要在 stable-tree中寻找, 根据页面内容,寻找 stable-tree中是不是有相同的页面。
  • 在unstable-tree中查找, 如果 unstable-tree中没有该page对应的节点, 插入。 如果找到, 合并两个页面,并从 unstable tree 移动到 stable tree中。

  • 注意:如果在 unstable-tree或者stable-tree中发生和页面合并的动作, 需要通过 rmap机制,更新 页表结构pte指向合并的ksm页面

    • 这里的rmap机制在ksm中使用,相应数据结构是rmap_item

      rmap_item:

      通过address 和 mm 找到vma

      结合 page(提供),可以找到vma中的页表项

可合并VMA设置

1
2
3
madvise
	-> madvise_behavior
		-> ksm_madvise
  • 如果任务的内存管理结构mm_struct还没有加入到ksm守护进程的 mm_slots链表中, 加入链表

疑问

mm_slot中保存rmap_item 链表,必要性是?

max_shared_page之后 , stable-tree变成线性结构?

stable-tree中的migration-node

参考

https://www.cnblogs.com/arnoldlu/p/8335524.html

https://www.lagou.com/lgeduarticle/52407.html

https://blog.csdn.net/zhongnanjun_3/article/details/21391321

https://zhuanlan.zhihu.com/p/67435420

https://www.kernelnote.com/entry/linux-ksm-merge