Linux 操作系统原理 — 内存 — KSM 内存页共享的性能问题
目录
Linux 的共享内存
进程访问物理内存空间的原理:在 Linux 的虚拟存储器中,用户进程的页表项和物理地址是多对一的关系,即多个页表项可以对应一个物理页面,这就是实现共享内存的底层支撑(几个进程同时共享物理内存)。
多进程间使用共享内存进行通信:在 Linux 操作系统中使用文件或管道的方式来进行多进程之间的通信会有很多局限性,比如效率的问题,并且进程间通信使用文件描述符不如内存地址访问来得方便,于是多进程间以共享内存的方式进行通信就成了一个不错的选择。
Linux 在编程上提供了多种使用共享内存的方案,两个运行中的进程共享数据,是进程间通信的高效方法,可有效减少数据拷贝的次数:
- mmap 内存共享映射。
- XSI 共享内存。
- POSIX 共享内存。
KSM 共享内存页
KSM(Kernel Shared Memory)是 Linux Kernel 的一种内存共享机制,在 2.6.36 版本引入。简而言之,KSM 用于合并具有相同内容的物理主存页面以减少页面冗余。在 Kernel 中有一个 KSM 守护进程 ksmd,它会定期扫描用户向它注册的内存区域,寻找到相同的页面就会将其合并,并用一个添加了写保护的页面来代替。当有进程尝试写入该页面时,Kernel 会自动为其分配一个新的页面,然后将新数据写入到这个新页面,这就是典型的 COW 机制。类似的,存储技术中有一个称为去耦合(de-duplication)的技术,通过删除冗余数据(基于数据块,或者基于更大的数据片段,比如文件)来减少已存储的数据。公共数据片段被合并(以一种 COW 方式),释放空间供其他用途。使用这种方法,存储成本更低,最终需要的存储器也更少。
KSM 最初被应用到 KVM 上,因为事实证明,如果虚拟化了许多相同的操作系统和应用程序组,那么宿主机上许多内存页面都是相同的。假如操作系统和应用程序代码以及常量数据在 VMs 之间相同,那么这个特点就很有用。当页面惟一时,它们可以被合并,从而释放内存,供其他应用程序使用。将多个 VMs 具有的相同内存页合并(共享),可以腾出更多的可用物理内存。
实际上,KSM 可以应用于任何应用。KSM 仅仅会合并匿名页面,不会对文件映射的页面做处理,经过 KSM 合并的页面最初是被锁定的内存中的,但是现在已经可以像其他页面一样被换出到交换区了。但是共享页一经换出,其共享的特性就被打破,再次换入的时候,ksmd 必须重新对其处理。
前面提到,KSM 仅仅会扫描那些向其注册的区域,就是向 KSM 模块注册了如果条件允许可以被合并的区域,通过 madvise 系统调用可以做到这点 int madvise(addr, length, MADV_MERGEABLE)
。同时,应用也可以通过调用 int madvise(addr, length, MADV_UNMERGEABLE)
来取消这个注册,从而让页面恢复私有特性。但是该调用可能会造成内存超额,造成 unmerge 失败,很大程度上会造成唤醒 Out-Of-Memory killer,杀死当前进程。如果 KSM 没有在当前运行的 Kernel 启用,那么前面提到的 madvise 调用就会失败,如果内核配置了 CONFIG_KSM=y
,调用一般是会成功的。
KSM 的管理和监控通过 sysfs(位于根 /sys/kernel/mm/ksm)执行。
- pages_to_scan:定义一次给定扫描中可以扫描的页面数。
- sleep_millisecs:定义执行另一次页面扫描前 ksmd 休眠的毫秒数。
- max_kernel_pages:定义 ksmd 可以使用的最大页面数(默认值是可用内存的 25%,但可以写入一个 0 来指定为无限)。
- merge_across_nodes:控制不同 NUMA 节点内存的合并,如果被设置成 0,则只合并当前 NUMA 节点的内存。
- run:控制 ksmd 的运行
- 0 表示停止 ksmd,但是保持合并的页面;
- 1 表示运行 ksmd;
- 2 表示停止 ksmd 并请求取消合并所有合并页面。
KSM 合并效果会实时显示在下面文件:
- pages_shared:KSM 正在使用的不可交换的内核页面的数量。
- pages_sharing:一个内存存储指示。
- pages_unshared :为合并而重复检查的惟一页面的数量。
- pages_volatile:频繁改变的页面的数量。
- full_scans:表明已经执行的全区域扫描的次数。
KSM 作者定义:较高的 pages_sharing/pages_shared 比率表明高效的页面共享(反之则表明资源浪费)。
性能问题
需要注意的是,应用 KSM 的时候要慎重考虑,因为 KSM 扫描相同的页面的过程会消耗较多的 CPU 资源,在对虚拟机性能要求苛刻的环境中一般都会禁用 KSM。关闭 KSM,可以让作为 Hypervisor 的 Linux Kernel(KVM)在负载增加时候,保证虚拟机的响应速度。这里再次印证了一句名言:计算机艺术永远是时间与空间的较量。
Shm 接口
- shmget 创建共享内存。
- shmat 启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
- shmdt 将共享内存从当前进程中分离。
文章来源: is-cloud.blog.csdn.net,作者:范桂飓,版权归原作者所有,如需转载,请联系作者。
原文链接:is-cloud.blog.csdn.net/article/details/106871278
- 点赞
- 收藏
- 关注作者
评论(0)