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
页面检查和合并过程
- 首先在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