本文讨论的 swap基于Linux4.4内核代码 。Linux内存管理是一套非常复杂的系统,而swap只是其中一个很小的处理逻辑。主要是:swap、swappiness及kswapd原理,swap分区优先级的妙用。
解决以下问题:
1、 swap到底是干嘛的?
2、 什么是内存水位标记?
3、 swap分区的优先级(prIOrity)有啥用?
我们一般所说的swap,指的是一个交换分区或文件。在Linux上可以使用swapon -s命令查看当前系统上正在使用的交换空间有哪些,以及相关信息:
$ swapon -s filename Type Size Used Priority /dev/dm-4 partition 33554428 0 -1
从功能上讲,交换分区主要是在内存不够用的时候,将部分内存上的数据交换到swap空间上,以便让系统不会因内存不够用而导致oom或者更致命的情况出现。
所以,当内存使用存在压力,开始触发内存回收的行为时,就可能会使用swap空间。
内核对swap的使用实际上是跟内存回收行为紧密结合的。那么关于内存回收和swap的关系,我们需要思考以下几个问题:
下面我们就从这些问题出发,一个一个进行分析。
为什么要进行内存回收?
根据这个enum可以看到,内存回收主要需要进行扫描的链表有如下4个:
就是说,内存回收操作主要针对的就是内存中的文件页(file cache)和匿名页。
关于活跃(active)还是不活跃(inactive)的判断内核会使用lru算法进行处理并进行标记,我们这里不详细解释这个过程。
整个扫描的过程分几个循环:
4.进行swap的时候,先对inactive的页进行换出;
5.如果是file的文件映射page页,则判断其是否为脏数据,如果是脏数据就写回,不是脏数据可以直接释放。
这样看来, 内存回收这个行为会对两种内存的使用进行回收:
因为针对filebased的内存,没必要进行交换,其数据原本就在硬盘上,回收这部分内存只要在有脏数据时写回,并清空内存就可以了,以后有需要再从对应的文件读回来。
内存对匿名页和文件缓存一共用了 四条链表 进行组织,回收过程主要是针对这四条链表进行扫描和操作。
那么如何描述内存使用的压力呢?
Linux内核使用水位标记(watermark)的概念来描述这个压力情况。
Linux为内存的使用设置了三种内存水位标记:high、low、min。他们 所标记的含义分别为:
内存回收行为就是基于剩余内存的水位标记进行决策的:
当系统剩余内存低于watermark[low]的时候,内核的kswapd开始起作用,进行内存回收。直到剩余内存达到watermark[high]的时候停止。
如果内存消耗导致剩余内存达到了或超过了watermark[min]时,就会触发直接回收(direct reclaim)。
明白了水位标记的概念之后,zonefile zonefree <= high_wmark_pages(zone)这个公式就能理解了。
这里的zonefile相当于内存中文件映射的总量,zonefree相当于剩余内存的总量。
内核一般认为,如果zonefile还有的话,就可以尽量通过清空文件缓存获得部分内存,而不必只使用swap方式对anon的内存进行交换。
整个判断的概念是说,在全局回收的状态下(有global_reclaim(sc)标记),如果当前的文件映射内存总量 剩余内存总量的值评估小于等于watermark[high]标记的时候,就可以进行直接swap了。
这样是为了防止进入cache陷阱,具体描述可以见代码注释。
这个判断对系统的影响是, swappiness设置为0时,有剩余内存的情况下也可能发生交换。
swap的相关操纵命令
可以使用mkswap将一个分区或者文件创建成swap空间。swapon可以查看当前的swap空间和启用一个swap分区或者文件。swapoff可以关闭swap空间。
我们使用一个文件的例子来演示一下整个操作过程:
制作swap文件:
启用swap文件:
关闭swap空间:
在使用多个swap分区或者文件的时候,还有一个优先级的概念(Priority)。
在swapon的时候,我们可以使用-p参数指定相关swap空间的优先级, 值越大优先级越高 ,可以指定的数字范围是-1到32767。
内核在使用swap空间的时候总是先使用优先级高的空间,后使用优先级低的。
当然如果把多个swap空间的优先级设置成一样的,那么两个swap空间将会以轮询方式并行进行使用。
如果两个swap放在两个不同的硬盘上,相同的优先级可以起到类似RAID0的效果,增大swap的读写效率。
另外,编程时使用mlock()也可以将指定的内存标记为不会换出,具体帮助可以参考man 2 mlock。
关于swap的使用建议,针对不同负载状态的系统是不一样的。有时我们希望swap大一些,可以在内存不够用的时候不至于触发oom-killer导致某些关键进程被杀掉,比如数据库业务。
也有时候我们希望不要swap,因为当大量进程爆发增长导致内存爆掉之后,会因为swap导致IO跑死,整个系统都卡住,无法登录,无法处理。
这时候我们就希望不要swap,即使出现oom-killer也造成不了太大影响,但是不能允许服务器因为IO卡死像多米诺骨牌一样全部死机,而且无法登陆。跑cpu运算的无状态的apache就是类似这样的进程池架构的程序。
觉得有用的关注下哦~
,