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- ...
随机推荐
- ByteHouse高性能向量检索实践——“以图搜图”
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 随着 LLM 技术的发展,向量检索与向量数据库也受到业界持续关注,它们能够为LLM提供外置记忆单元,通过提供与 ...
- 【郝斌C ST】指针 swap问题
C语言 指针 swap问题 在主函数种实现变量的交换 现在我们把这交换的行为封装进方法中 swap函数确实进行了交换,打印也是10和5了,但是下面a和b的结果还是5和10 - 形参i 和 形参j 并不 ...
- 【Java】 WebService 校验机制
测试环境域名 不可见 正式环境域名 不可见 1.2.安全校验凭证 accessId(授权ID) 测试/正式待定 securityKey(加密密钥) 测试/正式待定 1.3.安全校验机制 1.3.1.在 ...
- Streamlit运行出现ModuleNotFoundError: No module named ‘altair.vegalite.v4‘ —— ModuleNotFoundError: No module named 'altair.vegalite.v4'
参考: https://blog.csdn.net/ikun_King/article/details/131852167 解决方法: pip install altair=4.2.2
- 中国2023年GDP增速5.2%
在中美贸易战和三年全球疫情的大背景下,我国的经济依旧保持强有力的增速,这表明了经济发展不断转好,一切恢复到疫情和贸易战之前也是有待期望的.
- AI实践者师生夏令营讲座视频:南京大学Lamda实验室(周志华 团队)讲座视频 —— 强化学习的局限性与展望
视频地址: 周志华团队与Intel团队的讲座视频--强化学习的局限性与未来展望 视频链接地址: https://bizwebcast.smarket.com.cn/b975d6d9969a42cba9 ...
- 在深度学习的视觉VISION领域数据预处理的魔法常数magic constant、黄金数值的复现: mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225]
代码: https://gist.github.com/pmeier/f5e05285cd5987027a98854a5d155e27 import argparse import multiproc ...
- 安装华为软件昇腾mindspore-gpu-1.9.0失败记录
官网安装地址: https://www.mindspore.cn/install PS: 不得不说华为的软件是愈发的不好用了,这个mindspore老版本去年我是使用过的,安装也是比较方便的,搞不清这 ...
- 修改ListCtrl控件列标题文本居左显示
修改ListCtrl控件标题文本居左显示 原来的列标题文本是居中显示: 现在要把列表文本居中改为居左显示 其方法如下: 获得标题控件句柄 g_listCtrl.m_hWnd为ListCtrl控件的句柄 ...
- 浅谈下javascript的proxy和reflect
近日喜欢上了uniapp和vue,但看到相关程序代码中频繁出现了proxy和reflect的使用,于是进行了一番学习,现总结如下. Proxy和Reflect是ES6(ECMAScript 2015) ...