KSM可合并重复匿名内存页以节省物理内存,需先确认内核支持(CONFIG_KSM=y且/sys/kernel/mm/ksm/存在),再通过systemd服务或sysfs接口启用,配置扫描参数,应用需调用madvise(MADV_MERGEABLE)标记内存区域,最后通过pages_shared等统计值验证效果。

如果您在运行KVM虚拟化环境或部署多个内存内容高度相似的应用进程时,发现物理内存占用偏高,但CPU资源相对富余,则可能是由于重复的匿名内存页未被合并。以下是启用Linux内核同页合并(KSM)功能的具体操作步骤:
一、确认系统支持KSM
KSM功能需内核编译时启用CONFIG_KSM=y,且/sys/kernel/mm/ksm/目录存在才可使用。该目录是KSM运行状态与参数控制的核心接口。
1、执行命令检查KSM接口是否存在:ls /sys/kernel/mm/ksm/
2、若输出包含run、pages_shared、sleep_millisecs等文件,则说明内核已支持KSM;若提示“No such file or directory”,则需检查内核配置:zcat /proc/config.gz | grep CONFIG_KSM 或 grep CONFIG_KSM /boot/config-$(uname -r)
3、若返回CONFIG_KSM=y,但/sys/kernel/mm/ksm/仍不存在,可能因ksmd内核线程未初始化,需尝试手动触发模块加载(如适用):modprobe ksm
二、启用KSM扫描服务
ksm服务负责启动并管理ksmd内核线程,是标准发行版中推荐的启用方式,具备服务生命周期管理能力。
1、启动KSM服务:sudo systemctl start ksm
2、设置开机自启:sudo systemctl enable ksm
3、验证服务状态:sudo systemctl is-active ksm,预期输出为“active”
三、直接写入sysfs接口启用
当系统未提供systemd服务(如精简容器镜像、定制内核环境),或需快速验证KSM行为时,可绕过用户空间服务,直接操作内核接口。
1、启用KSM扫描:echo 1 | sudo tee /sys/kernel/mm/ksm/run
2、确认启用成功:cat /sys/kernel/mm/ksm/run,预期输出为“1”
3、若需临时停用:echo 0 | sudo tee /sys/kernel/mm/ksm/run
四、配置KSM扫描行为参数
调整pages_to_scan和sleep_millisecs可控制KSM扫描粒度与频率,在内存节省与CPU开销之间取得平衡。
1、设置每次扫描页数(默认100):echo 200 | sudo tee /sys/kernel/mm/ksm/pages_to_scan
2、设置扫描间隔毫秒数(默认20):echo 50 | sudo tee /sys/kernel/mm/ksm/sleep_millisecs
3、限制NUMA节点间合并(推荐生产环境启用):echo 0 | sudo tee /sys/kernel/mm/ksm/merge_across_nodes
五、为应用内存区域注册KSM候选
KSM仅对显式标记为MADV_MERGEABLE的匿名内存区域生效,应用程序需主动调用madvise告知内核该地址空间可参与合并。
1、在分配私有匿名内存后(如mmap(MAP_ANONYMOUS|MAP_PRIVATE)),调用:madvise(addr, length, MADV_MERGEABLE)
2、若需取消合并资格(例如敏感数据区域):madvise(addr, length, MADV_UNMERGEABLE)
3、注意:该调用在未启用KSM的内核上会返回EINVAL;在KSM已启用但未运行时仍会成功注册,待ksmd启动后自动生效
六、监控KSM实际效果
启用后应立即读取sysfs统计值,确认KSM是否开始识别并合并重复页面。
1、查看已共享页数:cat /sys/kernel/mm/ksm/pages_shared
2、查看因共享节省的页数:cat /sys/kernel/mm/ksm/pages_sharing
3、查看未共享但曾被扫描的页数:cat /sys/kernel/mm/ksm/pages_unshared
4、查看当前扫描间隔:cat /sys/kernel/mm/ksm/sleep_millisecs











