KSM的使用
使能KSM
KSM只会处理通过madvise系统调用显式指定的用户进程地址空间,因此用户程序想使用这个功能就必须在分配地址空间时显式地调用madvise(addr,length,MADV_MERGEA BLE)。如果用户想在KSM中取消某一个用户进程地址空间的合并功能,也需要显式地调用madvise(addr,length,MADV_UNMERGEABLE)。 下面是测试KSM的test.c程序的代码片段,使用mmap():来创建一个文件的私有映射,并且调用memset()写入这些私有映射的内容缓存页面中。
《测试KSM的test.c程序的代码片段》
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
char *buf;
char filename[64]="";
struct stat stat;
int size =100*4096;
int fd =0;
strcpy(filename, argv[1]);
fd = open(filename,O_RDWR | O_CREAT,0664);
fstat(fd, &stat);
buf = mmap (NULL,stat.st_size,PROT_WRITE,MAP_PRIVATE,fd,0);
memset(buf,0x55,stat.st_size);
madvise(buf,stat.st_size, MADV_MERGEABLE);
while (1)
sleep(1);
}
编译上述test.c程序。
gcc test.c -o test
使用dd命令创建一个ksm.dat文件,即创建100MB大小的文件。
echo 1 >/sys/kernel/mm/ksm/run
运行test.c程序。
#./test ksm.dat
过一段时间之后,查看系统有多少页面合并了。
root@benshushu#cat /sys/kernel/mm/ksm/pages_sharing
25500
root@benshushu#cat /sys/kernel/mm/ksm/pages_shared
100
root@benshushu:/home#cat /sys/kernel/mm/ksm/pages_unshared
0
可以看到pages_shared为100说明系统有100个共享的页面。若有100个页面的内同,它们可以合并成一个页面,这时pages_shared为1。 pages_sharing 为25500说明有25500个页面合并了。 100MB的内存可存放25600个页面。因此,我们可以看到,KSM把这25600个页面分别合并成1共享的页面,每一个共享页面里共享了其他的255个页面,为什么会这样?我们稍后详细解析。 pages_unshared表示当前未合并页面的数量。
rootebenshushut cat /sys/kernel/mn/ksm/stable_node_chains
1
rootebenshushut cat /sys/kernel/mm/ksm/stable_node_dups
100
stable_node_chains表示包含了链式的稳定节点的个数,当前系统中为1,说明只有一个链式的稳定节点,但是这个稳定的节点里包含了链表。 stable_node_dups表示稳定的节点所在的链表包含的元素总数。 KSM的sysfs节点在/sys/kernel/mm/ksm/目录下,其主要节点的描述如下所示。
- run:可以设置为0~2。若设置0,暂停ksmd内核线程;若设置1,启动ksmd内核线程;若设置2,取消所有已经合并好的页面
- full_scans: 完整扫描和合并区域的次数
- pages_volatile: 表示还没扫描和合并的页面数量。若由于页面内容更改过快导致两次计算的校验值不相等,那么这些页面是无法添加到红黑树里的
- sleep_millisecs: ksmd内核线程扫描一次的时间间隔
- pages_to_scan: 单次扫描页面的数量
- pages_shared: 合并后的页面数。如果100个页面的内容相同,那么可以把它们合并成一个页面,这时pages_shared的值为1
- pages_sharing: 共享的页面数。如果两个页面的内容相同,它们可以合并成一个页面,那么有一个页面要作为稳定的节点,这时pages_shared的值为1,pages_sharing也为1。第3个页面也合并进来后,pages_sharing的值为2,表示两个页面共享同一个稳定的节点
- pages_unshared: 当前未合并页面数量
- max_page_sharing: 这是在Linux4.3内核中新增的参数,表示一个稳定的节点最多可以合并的页面数量。这个值默认是256
- stable_node_chains: 链表类型的稳定节点的个数。每个链式的稳定节点代表页面内容相同的KM页面。这个链式的稳定节点可以包含多个dup成员,每个dup成员最多包含256个共享的页面
- stable_node_dups: 链表中dup成员的个数。这些dup成员会连接到链式的稳定节点的hlist链表中
KSM在初始化时会创建一个名为ksmd的内核线程。
<mm/ksm.c>
static int __init ksm_init(void)
{
ksm_thread = kthread_run(ksm_scan_thread, NULL, "ksmd");
}
subsys_initcall(ksm_init);
在tes.c程序中创建私有映射(MAP_PRIVATE)之后,显式地调用madvise系统调用把用户进程地址空间添加到 Linux内核的KSM系统中。
<madvise()->ksm_madvise()-> ksm_enter()>
int __ksm_enter(struct mm_struct *mm)
{
mm_slot = alloc_mm_slot();
insert_to_mm_slots_hash(mm, mm_slot);
list_add_tail(&mm slot->mm_list, &ksm_scan.mm_slot->mm list);
set_bit(MME_VM_MERGEABLE, &mm->flags);
}
ksm_enter()函数会把当前的 mm_struct数据结构添加到 mm_slots_hash哈希表中。另外把 mm_slot添加到 ksm_scan.mm_slot->mm_list 链表中。最后,设置mm->flags中的 MMF_VM_MERGEABLE标志位,表示这个进程已经被添加到KSM系统中.
<ksm内核线程>
static int ksm_scan_thread(void *nothing)
{
while (!kthread_should_stop())
if (ksmd_should_run())
ksm_do_scan(ksm_thread_pages_to_scan)
if (ksmd_should_run()) {
sleep_ms =READ_ONCE(ksm_thread_sleep_millisecs);
wait_event_interruptible_timeout(ksm_iter_wait,
sleep_ms != READ_ONCE(ksm_thread_sleep_millisecs),
secs_to_jiffies(sleep_ms));
}
return 0;
}
ksm_scan_thread()是ksmd内核线程的主干,它运行 ksm_do_scan()函数,扫描和合并100个页面,见 ksm_thread_pages_to_scan参数,然后等待20ms,见 ksm_thread_sleep_millisecs参数,这两个参数可以在/sys/kernel/mm/ksm目录下设置和修改。
<ksmd内核线程>
static void ksm_do_scan(unsignd int scan_npages)
{
while(scan_npages-- && likely(!freezing(current))) {
cond_resched();
rmap_item = scan_get_next_rmap_item(&page);
if (!rmap_item)
return;
cmp_and_merge_page(page, rmap_item);
put_page(page)
}
}
ksm_do_scan()函数在while循环中尝试合并scan_npages个页面, scan_get_next_rmap_item()获取一个合适的匿名页面。 cmp_and_merge_page()函数会让页面在KSM中稳定和不稳定的两棵红黑树中查找是否有可以合并的对象,并且尝试合并他们。
KSM基本实现
为了让读者先有一个初步的认识,本节先介绍Lnux4.13内核之前的KSM实现,后文会介绍Linux5.0内核中的实现。
KSM机制下采用两棵红黑树来管理扫描的页面和己经合并的页面。第一棵红黑树称为不稳定红黑树,里面存放了还没有合并的页面;第二棵红黑树称为稳定红黑树,已经合并的页面会生成一个节点,这个节点为稳定节点。如两个页面的内容是一样的,KSM扫描并发现了它们,因此这两个页面就可以合并成一个页面。对于这个合并后的页面,会设置只读属性,其中一个页面会作为稳定的节点挂载到稳定的红黑树中之后,另外一个页面就会被释放了。但是这两个页面的 rmap_item数据结构会被添如到稳定节点中的 hist 链表中,如下图所示。

我们假设有3个VMA(表示进程地址空间,VMA的大小正好是一个页面的大小,分别有3个页面映射这3个VMA。这3个页面准备通过KSM来扫描和合并,这3个页面的内容是相同的。具体步骤如下。
- 3个页面会被添加到KSM中,第一轮扫描中分别给这3个页面分配 rmap_item数据结构来描述它们,并且分别给它计算校验和,如图(a)所示
- 第二轮扫描中,先扫描page0,若当前稳定的红黑树没有成员,那么不能比较和加入稳定的红黑树。接着,第二次计算校验值,如果 page0的校验值没有发生变化,那么把page0的rmap_item()添加到不稳定的红黑树中,如图(b)所示。如果此时校验值发生了变化,说明页面内容发生变化,这种页面不适合添加到不稳定的红黑树中
- 扫描 page1,当前稳定的红黑树中没有成员,略过稳定的红黑树的搜索。搜索不稳定的红黑树,遍历红黑树中所有成员。 page1发现自己的内容与不稳定的红黑树中的 rmap_item()一致,因此尝试将page0和 page1合并成一个稳定的节点,合并过程就是让WMA0对映的虚拟地址、vaddr0映时到page1上。,并且把对应的PTE属性修改成只读展性。另外,VMA1映射到 page1的PTE属性也设置为只读属性。新创建一个稳定的节点,这个节点包含了page1的页帧号等信息,把这个稳定的节点添加到稳定的红黑树中。把代表page0的 map _item0和page1的rmap_item1添加到这个稳定的节点的hlist链表中,最后释放page0页面,如图(c)所示
- 扫描page2。因为稳定的红黑树中有成员,因此,先和稳定的红黑树中的成员进行比较,检査是否可以合并。若发现page2的内容和稳定的节点内容一致,那么把VMA2中的vaddr2映射到稳定的节点对应的 page1上,并且把PTE属性设置为只读属性。把代表page2的rmap_item2添加到稳定的节点的 hlist 链表中,最后释放page2页面,如图(d)所示

KSM的使用的更多相关文章
- 虚拟机NUMA和内存KSM
KSM技术可以合并相同的内存页,即使是不同的NUMA节点,如果需要关闭跨NUMA节点的内存合并,设置/sys/kernel/mm/ksm/merge_across_nodes参数为0.或者可以关闭特定 ...
- KSM剖析——Linux 内核中的内存去耦合
简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging) 允许这个系统管理程序通 ...
- Linux内存管理 (17)KSM
专题:Linux内存管理专题 关键词:KSM.匿名页面.COW.madvise .MERGEABLE.UNMERGEABLE. KSM是Kernel Samepage Merging的意思,用于合并内 ...
- linux下的KSM内存共享机制分析
2017-04-26 KSM是内核中的一种内存共享机制,在2.6.36版本的内核中开始引入,简单来说就是其会 合并某些相同的页面以减少页面冗余.在内核中有一个KSM守护进程 ksmd,它定期扫描用户向 ...
- P1306 斐波那契公约数(ksm+结论)
题目描述 对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少? Update:加入了一组数据. 输 ...
- KSM概念学习
KSM: Kernel SamePage Merging 内核同页合并 简介 KSM允许内核在两个或多个进程(包括虚拟客户机)之间共享完全相同的内存页. KSM让内核扫描检查正在运行中的程序,并比较他 ...
- BZOJ3160万径人踪灭
Description Input & Output & Sample Input & Sample Output HINT 题解: 题意即求不连续但间隔长度对称的回文串个数. ...
- lucene+IKAnalyzer实现中文纯文本检索系统
首先IntelliJ IDEA中搭建Maven项目(web):spring+SpringMVC+Lucene+IKAnalyzer spring+SpringMVC搭建项目可以参考我的博客 整合Luc ...
- 利用Bootstrap快速搭建个人响应式主页(附演示+源码)
1.前言 我们每个程序员都渴望搭建自己的技术博客平台与他人进行交流分享,但使用别人的博客模板没有创意.做网站后台的开发人员可能了解前端,可是自己写一个不错的前端还是很费事的.幸好我们有Bootstra ...
- java web学习总结(二十一) -------------------模拟Servlet3.0使用注解的方式配置Servlet
一.Servlet的传统配置方式 在JavaWeb开发中, 每次编写一个Servlet都需要在web.xml文件中进行配置,如下所示: 1 <servlet> 2 <servlet- ...
随机推荐
- 关于visual studio的一个bug
本人初学链表,如有错误多多包涵 快马加鞭,这期只写一个问题.我好像在vs里面发现了一个bug 不管是vs2022还是vs2010都无法正常运行.关于cin.string.链表的问题 #include& ...
- 2023/4/16 SCRUM个人博客
1.我昨天的任务 大体学习并了解初始化pyqt5的一些可视化问题 2.遇到了什么困难 对于py的字典使用 3.我今天的任务 学习了easydict库的基本操作
- PKUWC2024游记
PKUWC2024 游记 day -???? 得知今年冬令营在育才,非常高兴不用出远门了. day 1 当天上午 7:00 起来,然后做车去报道,非常堵车.感觉育才环境挺好的,~不像某人在读学校一样. ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-59 - 判断元素是否显示 - 上篇
1.简介 有些页面元素的生命周期如同流星一闪,昙花一现.我们也不知道这个元素在没在页面中出现过,为了捕获这一美好瞬间,让其成为永恒.我们就来判断元素是否显示出现过. 在操作元素之前,可以先判断元素的状 ...
- Jmeter的安装(Windows)
1.选择和本机JDK兼容的jmeter版本下载 Jmeter历史版本下载地址:https://archive.apache.org/dist/jmeter/binaries/ 此处我的jmeter5. ...
- 【Windows】(USB热点连接)使用手机给主机提供热点连网
1.问题起源 昨天跟和几个哥们一起装机,发现安装好的系统, 直连网卡提示安装成功,但是网络设置显示未连接 找不到其他原因的办法下,我们看能不能使用手机对电脑进行连网 2.解决过程 我想到的是,先从手机 ...
- 强化学习:连续控制问题中Actor-Critic算法的linear baseline
最近在看连续控制问题,看到了一个Actor-Critic算法中手动扩展features和设置linear baseline的方法,这些方法源自论文:<Benchmarking Deep Rein ...
- How to 'apt-get install python-opengl' on Ubuntu22.04
ImportError: Error occurred while running `from pyglet.gl import *` HINT: make sure you have OpenGL ...
- 在vscode中通过修改launch.json文件为项目添加环境变量——在launch.json文件中修改env变量
在vscode中launch.json文件具有十分重要的作用,在vscode中可以通过修改launch.json文件修改调试和运行代码时的设置. 本文假设已对vscode有初步了解,已可以创建laun ...
- LVS-TUN隧道模式
当然可以.以下是按照您的要求整理的表格形式的实验手册: 主机名称 网卡信息 安装应用 系统 Client客户端 192.168.2.101 无 RHEL8/CentOS8 Lvs服务器(DR) DIP ...