每个内存管理区(zone)都有一个lowmem_reserve字段,它代表本管理区预留的物理内存大小。所谓预留,那就是说肯定还是有用的,只是用的时机不同。
之前的文章中由介绍过water mark水位值,系统中已经为每个管理区(zone)内存大小设定了三个水位值了,分别时WMARK_HIGH/WMARK_LOW/WMARK_MIN。怎么这里又多出来一个lowmem_reserve?
在内存分配时,分配器会根据不同的水位执行不同的动作,首先内存分配器会扫描所有zonelist中的管理区,按照zonelist中的分配顺序依次检查管理区中能否分配对应的内存。这几个值都是用来确定最终要从哪个管理区来分配内存这个问题的。
内存申请时有一个fallback的过程,通过gfp flag得到zone并不一定是最终申请内存所在的zone,fallback的顺序如下:
fallback list:MOVABLE=>HIGHMEM=>NORMAL=>DMA32=>DMA
通过fallback顺序依次检测具备合适空闲内存的zone用于本次申请,那么对于高位的zone过量申请可能导致低位的zone被用尽,从而影响低位的申请,比如DMA内存的申请失败可能引起系统异常,那么lowmem_reserve就是为了防止高位zone在fallback时过度使用自己的内存。低位zone会优先保证自己的内存分配,确实有一定的富余的情况下,才可以提供给更高位的zones。通过系统文件/proc/zoneinfo中的"protection"可以看到各个zone的lowmem_reserve配置。
内存申请过程大概如下:
1.首先以low water mark位标准来循环检测一遍,当发现zonelist中存在空闲内存在low water mark之上的管理区时,我们优先就从它开始分配。
判断标准需要加入lowmem_reserve来进行:
if (!order && (free_pages - cma_pages) > mark + z->lowmem_reserve[classzone_idx])
return true;
2.如果发现所有管理区的内存都已经低于low water mark了,那么进一步利用min water mark来进行循环检测,判断方法和上面一致,寻找空闲内存在min water mark之上的管理区。
3.当然随着我们不停的检测,会触发系统的页面回收机制了,触发机制就是唤醒kswapd内核线程来对页框进行回收。当回收的页面能满足我们需求时,就会返回我们的需求了.