本文转载自微信公众号《人人都是极客》,作者布道者Peter。转载本文请联系大家是极客公众号。partitionpageframeallocator的水位在讲partitionpageframeallocator分配内存的时候,在进入伙伴算法之前使用函数zone_watermark_fast()根据水位来判断当前内存情况。如果内存足够,则使用伙伴算法进行分配,如果不够,则通过node_reclaim回收内存。int__memininit_per_zone_wmark_min(void){unsignedlonglowmem_kbytes;intnew_min_free_kbytes;lowmem_kbytes=number_free_buffer_pages()*(PAGE_SIZE>>10);------(1)new_min_free_kbytes.=int_sqrt)*(lowmemif(new_min_free_kbytes>user_min_free_kbytes){free_min_free_kbytes;------(2)if(min_free_kbytes<128)min_free_kbytes=128;if(min_free_kbytes>65536)min_free_kbytes=655"36;_}warnse{;my_free_kbytesnotupdatedto%dbecauseuserdefinedvalue%dispreferred\n",new_my_free_kbytes,user_my_free_kbytes);}setup_per_zone_lowmem_reserve();-----(3)refresh_zone_state_thresholds();-----(4)#ifdefMAse);setup_min_s#endifreturn0;}core_initcall(init_per_zone_wmark_min)(1).nr_free_buffer_pages是获取ZONE_DMA和ZONE_NORMAL区中高于高位的总页数nr_free_buffer_pages=managed_pa??ges-high_pages(2).min_free_kbytes是总的最小大,min_free_kbytes=4*sqrt(lowmem_kbytes)(3).setup_per_zone_wmarks根据总的min值,加上每个zone在总内存中的比例,然后通过do_div计算出它们各自的min值,然后计算出每个zone的水位min、low、high关系:low=min*125%,高=最小*150%。min、low、high的比例关系与watermark_scale_factor有关。它可以通过/proc/sys/vm/watermark_scale_factor(4)设置。setup_per_zone_lowmem_reserve设置每个区域的lowmem_reserve大小。lowmem_reserve值可以通过/proc/sys/vm/lowmem_reserve_ratio修改。为什么要设置每个zone的reservedmemory?lowmem_reserve的作用是什么?我们知道,内核在分配内存时,会按照HIGHMEM->NORMAL->DMA的方向遍历。如果当前Zone分配失败,会尝试下一个Low-levelZone。我们可以想象应用进程通过内存映射申请HIGHMEM。如果此时HIGHMEMZone不能满足分配,就会尝试从NORMAL进行分配。这有问题。来自HIGHMEMZone的请求可能会耗尽NORMALZone的内存。最终的结果是NORMALZone没有内核正常分配的内存。因此,对于这种场景,可以通过预留内存lowmem_reserve[NORMAL]来使用NORMALZone。同样,当它从NORMALZone失败时,它会尝试从zonelist中的DMAZone申请,并通过lowmem_reserve[DMA]限制来自HIGHMEM和NORMAL的分配请求。$cat/proc/sys/vm/lowmem_reserve_ratio25632$cat/proc/zoneinfoNode0,zoneDMA32......pagesfree361678min674low2874high3314spanned523776present496128managed440432protection:(0,3998,3998)......Node0,zoneNormalpagesfree706981min1568low6681high7704spanned8912896present1048576managed1023570protection:(0,0,0)......Node0,zoneMovablepagesfree0min0low0high0spanned0present0managed0protection:(0,0,0)spanned:表示当前zone包含的所有pagesPresent:表示当前zone去除第一阶段内核保留内存后剩余的pagesManaged:表示当前zone的初始化去掉后,内核保留内存剩余的所有page都和上面arm64平台的值结合起来。例如,假设两个Zone分别包含440432和1023570页(实际上是/proc/zoneinfo中管理的字段的值)。如下图所示,利用各个区域的managedpages和lowmem_reserve_ratio计算出各个区域的lowmem_reserve值。可见结果与保护值相同。从这个图中可以看出水位的判断:如果freepages个数为min,zone很缺页,pagerecovery压力很大,应用程序写内存操作会被阻塞,直接在应用程序的进程上下文中进行Reclaim,即直接回收。如果空闲页数小于低值,kswapd线程将被唤醒。默认情况下,low值为min值的125%,比例值可以通过修改watermark_scale_factor来改变,如果freepage的值大于high值,kswapd线程会休眠。默认情况下,highvalue是minvalue的150%,可以通过修改watermark_scale_factor来改变scale值
