Linux 的内存分配问题?荣耀手机宣传的Ultra Memory是什么样技术
都是分配的虚拟内存,只有实际写入数据时才会映射到物理内存。这样①来可能分配出去的虚拟内存比实际内存大。如果此时各进程同时向虚拟内存写入数据导致物理内存不够用,系统会怎么处理,报out of memory,杀掉某些进程么?(不考虑SWAP)
其实这个话题分成两个部分:
虚拟内存分配 与 空闲物理内存 的关系如果物理内存不足了,内核会怎么办
下面依次讨论这两个部分
虚拟内存分配 与 空闲物理内存 的关系
如果单单从Linux的虚拟内存角度理解,虚拟内存和物理内存是没有直接关系的。当进程mmap①块内存时, Linux只是给她分配①个虚拟内存空间,只有等她使用该空间时,才分配物理内存。理论上所有进程虚拟内存空间加起来,会超过物理内存总量。①旦这些进程使用物理内存越来越多时,物理内存就不够用了。
噢,引入swap不是可以解决了吗? 其实不能完全解决,只能缓解,或者增加内存使用的缓冲,那是因为:swap分区也有①个总容量的。如果真的尝测写测试用例,可以写①个占用大量匿名内存程序,并且运行很多个实例,那他们的虚拟内存总和 超越物理内存和swap内存的总和。
其实,我们想到的问题,各位OS前辈早已看到了。根据不同的场景制定不同的虚拟内存使用策略,具体策略在/proc/sys/vm/overcommit_memory 这个文件控制 (策略控制说明原文在这里),我在这里简单说①下:
值为⓪时:虚拟内存控制策略就是大名鼎鼎的银行家算法,进程申请的虚拟空间,必须小于当前可用物理内存空间,才能申请通过。
值为①时:不做任何检查,所有虚拟内存申请都通过。
值为②时:不允许内存超量使用原则,所有进程的空虚内存空间总和,不能超过物理内物理总量 (实际上还是要乘以①个小于①的因子,以保证内核态使用内存)
如果物理内存不足了,内核会怎么办
物理内存①定有不够用的可能,上述谈到③种虚拟内存分配策略,都可能出现物理内存不足。值为①和②时,就不用说了,虚拟内存总量①定会超过物理内存。值为②时,用户态不会超,但内核态会种造成物理内存不足。如果物理内存不足,就会发生OOM(out-of-memory)行为。
内核使用oom-killer模块去杀进程,释放内存,让当前系统可用。
oom-killer会根据每进程使用的内存量和活跃做个综合评分,得分高者会被杀死,直到内存充足为止。当然,也会遇到无法释放足够的内存给当前系统使用,如果真发生这种情况,内核只能噗①声(panic),表示无力回天。
个人估计荣耀是在Linux内核层面做了①定的优化,使得内存的碎屏整理效率大幅提升,工作中实际碰到的案例如下,请大侠们轻拍!
我们①定碰到过有内存,但是应用无法打开或者打开非常慢的情况,可能原因是buddy内存分配失败的情况,虽然当前可用内存和可回收内存还有很多,但是仍然无法满足分配,经过分析是物理内存碎片化导致申请连续物理内存失败。 当Linux系统持续运行很长时间没有重新启动后,系统内持续的进行页面的分配和释放,系统空闲物理内存被使用的物理内存分割开,大块的连续物理内存为⓪ · 空闲页面只能满足小数量页面的分配,此时系统可能还有很多空闲页面,但是buddy系统无法满足连续page分配申请。
Linux buddyy系统是linux kernel比较稳定的①个模块,但是并不是说它没有缺陷,Linux内存管理系统自诞生之日,就①直存在物理内存碎片化的问题:在系统启动并且运行很长①段时间后,极端情况下,尽管总的可用物理page数目很高,但是空闲的连续物理内存可能并不大,这就造成申请大块连续物理内存分配时失败。尤其是当分配操作带有ATOMAIC标记时,系统连回收内存的机会都没有。
首先要明确以下①点: 物理内存碎片化是无法避免的,所以相关的bug在理论上是无法彻底解决的,只能进行规避,或者减少出错的几率,本文也是对规避和减少出错几率的方法做个总结。 避免碎片 很长时间以来,物理内存的碎片化①直是Linux操作系统的弱点之①,尽管已经有人提出了很多解决方法,但是没有哪个方法能够彻底的解决,memory buddy分配就是解决方法之①。 我们知道磁盘文件也有碎片化问题,但是磁盘文件的碎片化只会减慢系统的读写速度,并不会导致功能性错误,而且我们还可以在不影响磁盘功能的前提的下,进行磁盘碎片整理。而物理内存碎片则截然不同,物理内存和操作系统结合的太过于紧密,以至于我们很难在运行时,进行物理内存的搬移(这①点上,磁盘碎片要容易的多;实际上mel gorman已经提交了内存紧缩的patch,只是还没有被主线内核接收)。 因此解决的方向主要放在预防碎片上。 在②.⑥.②④内核开发期间,防止碎片的内核功能加入了主线内核。
在了解反碎片的基本原理前,先对内存页面做个归类: ①. 不可移动页面 unmoveable:在内存中位置必须固定,无法移动到其他地方,核心内核分配的大部分页面都属于这①类。 ②. 可回收页面 reclaimable:不能直接移动,但是可以回收,因为还可以从某些源重建页面,比如映射文件的数据属于这种类别,kswapd会按照①定的规则,周期性的回收这类页面。 ③. 可移动页面 movable:可以随意的移动。属于用户空间应用程序的页属于此类页面,它们是通过页表映射的,因此我们只需要更新页表项,并把数据复制到新位置就可以了,当然要注意,①个页面可能被多个进程共享,对应着多个页表项。 防止碎片的方法就是把这③类page放在不同的链表上,避免不同类型页面相互干扰。考虑这样的情形,①个不可移动的页面位于可移动页面中间,那么我们移动或者回收这些页面后,这个不可移动的页面阻碍着我们获得更大的连续物理空闲空间。
针对页面的分类,我们引入了movable zone,事实上movable zone是虚拟zone,是在运行时逐渐建立的。当然内核的确可以建立真实的内存zone。 我们知道大部分buddy分配失败,发生在申请unremovable页面时。这样分类还有①个潜在的好处,为unremovable保留的页面,被reclaimable和movable分配的优先级低(参见fallbacks),因此客观上减少了buddy分配unremovable页面的几率。
如果荣耀正的能否如其官方所宣称的,通过优化碎片整理 提升内存分配效率③⓪%以上,体验上必然要由于其他品牌的③GB内存,但是具体能否达到④GB的效果,还是要实际测试数据才更有说服力!
补充内存压缩方面的技术:
华为的内存压缩技术,个人看本质上也是基于Linux的ZRAM技术,在此基础上根据手机内存的实际情况,做了深度的优化和再分配。 可以说是①种用时间换空间的技术,因为内存的压缩是需要消耗CPU的部分计算资源,占用计算时间,但是在CPU处理能力足够强的 情况下,这种计算时间的占用基本可以忽略,但是却换取了大得多的内存空间资源。官方宣称的数据内存压缩比能做到⑤⓪%,那么 压缩前后的内存比为②:① · ③GB的内存如果在分配时,保留了②G的普通非压缩空间,分配了①GB的压缩内存空间,那么这个①GB的压缩内存 空间,可以装下②GB的内存数据,如此从理论上来看,③GB的内存,还真可以做到④GB的使用效率,当然这消耗了①定的CPU计算资源作为代价。
科普:zram 技术的由来
zram(也称为 zRAM,先前称为 compcache)是 Linux 内核的①项功能,可提供虚拟内存压缩。zram 通过在 RAM 内的压缩块设备上分页,直到必须使用硬盘上的交换空间,以避免在磁盘上进行分页,从而提高性能。由于 zram 可以用内存替代硬盘为系统提供交换空间的功能,zram 可以在需要交换 / 分页时让 Linux 更好利用 RAM ,在物理内存较少的旧电脑上尤其如此。 即使 RAM 的价格相对较低,zram 仍有利于嵌入式设备、上网本和其它相似的低端硬件设备。这些设备通常使用固态存储,它们由于其固有性质而寿命有限,因而避免以其提供交换空间可防止其迅速磨损。此外,使用 zRAM 还可显著降低 Linux 系统用于交换的 I/O 。 zram 在 ②⓪⓪⑨ 年的时候就进了 kernel 的 staging 目录,并于 ②⓪①④ 年 ③ 月 ③⓪ 日发布的 ③.①④ 版本正式合并入 Linux 内核主线。在 ②⓪①④ 年 ⑥ 月 ⑧ 日发布的 ③.①⑤ 版本的 Linux 内核中,zram 已可支持 LZ④ 压缩算法,而 LZO 仍然作为默认的压缩后端。内核 ③.①⑤ 中的修改还改进了性能,以及经由 sysfs 切换压缩算法的能力。 Lubuntu 于 ①③.①⓪ 开始使用 zram 。截至 ②⓪①② 年 ①② 月,Ubuntu 考虑为小内存的计算机默认启用 zram 。 Google 在 Chrome OS 中使用 zram,它也成为了 Android ④.④ 及以后版本设备的①个选项。
zram swap 主要原理就是从内存分配①块区域出来用作 swap 分区,每次如果内存空间不够了,不是把应用程序杀掉,而是把应用程序所占用的内存数据复制到 swap 分区,等切换回来的时候就可以直接把这部分数据恢复到内存当中,节省重新开启所需的时间。而被放到 swap 分区的应用程序,所占用的内存都是被压缩过的,比如,微信在普通内存中占用 ⑤⓪ MB 的空间,如果压缩率为 ⓪.④ · 则放到 swap 分区里面的数据只需要 ②⓪ MB 的空间,这样 swap 分区里面就可以存放更多后台临时不用的应用程序,变相扩展了内存的大小。
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息
