老白学编程Netdata学习ksm

编程

虚拟化背景

虚拟化不用多说了,一个物理机可以托管多个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。

以上是 老白学编程Netdata学习ksm 的全部内容, 来源链接: utcz.com/z/515981.html

回到顶部