码迷,mamicode.com
首页 > Web开发 > 详细

老白学编程 - Netdata学习 - ksm

时间:2020-04-29 18:59:34      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:线程   结束   实现   vmw   系统调用   成员   写保护   校验和   应用   

KSM 介绍

KSM是Kernel Samepage Merging,允许合并内容相同的页面。

虚拟化背景

虚拟化不用多说了,一个物理机可以托管多个VM;
假如操作系统和应用程序在vm之间有时访问的数据相同,这些页可以进行合并,以释放内存。 虽然KSM最初设计是用于基于内核的虚拟机, 但在非虚拟化环境中也非常有用。

KSM 核心

KSM核心设计思想是基于写时复制机制COW,也就是将内容相同的页面合并成一个只读页面,从而释放出空闲物理页面。

KSM的实现可以分为两部分:

  • 一是启动内核线程ksmd,等待唤醒进行页面扫描和合并;
  • 二是madvise唤醒内核线程ksmd。

KSM只会处理通过madvise系统调用显式指定的用户进程地址空间内存,因此用户想使用此功能必须显式调用madvise(addr, length, MADV_MERGEABLE)。
用户想取消KSM中某个用户进程地址空间合并功能,也需要显式调用madvise(addr, length, MADV_UNMERGEABLE)。

合并页面

一个典型的应用程序由以下5个内存部分组成:

        可执行文件的内存映射(page cache)
        程序分配使用的匿名页面
        进程打开的文件映射
        进程访问文件系统产生的cache
        进程访问内核产生的内核buffer(如slab)等

KSM只考虑进程分配使用的匿名页面.

原理

KSM使用红黑树设计了两棵树:stable树和unstable树。
KSM利用页面的校验值来比较unstable树的页面最近是否被修改过。

不稳定树,用于存储还不能理解为稳定的新页面。换句话说,作为合并候选对象的页面(在一段时间内没有变化)存储在这个不稳定树中。不稳定树中的页面不是写保护的。

稳定树,存储那些已经发现是稳定的且通过 KSM 合并的页面。为确定一个页面是否是稳定页面,KSM 使用了一个简单的 32 位校验和(checksum)。当一个页面被扫描时,它的校验和被计算且与该页面存储在一起。在一次后续扫描中,如果新计算的校验和不等于此前计算的校验和,则该页面正在更改,因此不是一个合格的合并候选对象。

页面分为物理页面和虚拟页面,多个虚拟页面同时映射到一个物理页面,因此需要把映射到该页所有PTE都解除后,才算是真正释放。
目前有两种做法:

  • 一是扫描每个进程中的VMA,由VMA的虚拟地址查询MMU页表找到对应的page数据结构,进而找到用户pte。然后对比KSM中的stable树中的stable树和unstable树,如果找到内容相同的页面,就把该pte设置成COW,映射到KSM页面中,从而释放出一个pte,这里只是释放出一个用户pte,而不是物理页面。如果该物理页面只有一个pte映射,那就是释放该页。
  • 二是直接扫描系统中的物理页面,然后通过反响映射来解除该页所有的用户pte,从而一次性释放出物理页面。

匿名页

struct page指向映射到用户虚拟内存空间的匿名页面,那么其成员mapping指向anon_vma。
mapping的低2位,表示匿名页面或者KSM。
KSM是匿名页面,或者说KSM是匿名页面的子集。

ksmd

KSM 作为内核中的守护进程(称为 ksmd)存在,它定期执行页面扫描,识别副本页面并合并副本,释放这些页面以供它用。KSM 执行上述操作的过程对用户透明。

例如,副本页面被合并(然后被标记为只读),但是,如果这个页面的其中一个用户由于某种原因更改该页面,该用户将(以 CoW 方式)收到自己的副本。可以在内核源代码 ./mm/ksm.c 中找到 KSM 内核模块的完整实现。

KSM 应用程序编程接口(API)通过 madvise 系统调用(见清单 1)和一个新的建议参数(advice parameter)MADV_MERGEABLE(表明已定义的区域可以合并)来实现。可以通过 MADV_UNMERGEABLE 参数(立即从一个区域取消合并任何已合并页面)从可合并状态删除一个区域。注意,通过 madvise 来删除一个页面区域可能会导致一个 EAGAIN 错误,因为该操作可能会在取消合并过程中耗尽内存,从而可能会导致更大的麻烦(内存不足情况)。

使用 KSM 进程处理一个单一的页面时,第一步是检查是否能够在稳定树中发现该页面。搜索稳定树的过程很有趣,因为每个页面都被视为一个非常大的数字(页面的内容)。一个 memcmp(内存比较)操作将在该页面和相关节点的页面上执行。如果 memcmp 返回 0,则页面相同,发现一个匹配值。反之,如果 memcmp 返回 -1,则表示候选页面小于当前节点的页面;如果返回 1,则表示候选页面大于当前节点的页面。尽管比较 4KB 的页面似乎是相当重量级的比较,但是在多数情况下,一旦发现一个差异,memcmp 将提前结束。

/sys/kernel/mm/ksm/run

$ ls /sys/kernel/mm/ksm/
full_scans          pages_sharing   run                                 stable_node_dups
max_page_sharing    pages_to_scan   sleep_millisecs
merge_across_nodes  pages_unshared  stable_node_chains
pages_shared        pages_volatile  stable_node_chains_prune_millisecs

  • run : 写0,禁用; 1 启用; 2 停止;
  • pages_shared:KSM 正在使用的不可交换的内核页面的数量。
  • pages_sharing:一个内存存储指示。
  • pages_unshared:为合并而重复检查的惟一页面的数量。
  • pages_volatile:频繁改变的页面的数量。

其他

VMware 的 ESX 服务器系统管理程序将这个特性命名为 Transparent Page Sharing (TPS),而 XEN 将其称为 Memory CoW。

来源:包头SEO

老白学编程 - Netdata学习 - ksm

标签:线程   结束   实现   vmw   系统调用   成员   写保护   校验和   应用   

原文地址:https://www.cnblogs.com/1156184981651a/p/12803524.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!