前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux分区页框分配器之水位

Linux分区页框分配器之水位

作者头像
刘盼
发布2020-07-22 15:58:59
1.2K0
发布2020-07-22 15:58:59
举报
文章被收录于专栏:人人都是极客人人都是极客

我们讲页框分配器的时候讲到了快速分配和慢速分配,其中伙伴算法是在快速分配里做的,忘记的小伙伴我们再看下:

代码语言:javascript
复制
static struct page *
get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
      const struct alloc_context *ac)
{
  for_next_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx, ac->nodemask)
  {
    if (!zone_watermark_fast(zone, order, mark, ac_classzone_idx(ac), alloc_flags))
    {
      ret = node_reclaim(zone->zone_pgdat, gfp_mask, order); 
      switch (ret) {
      case NODE_RECLAIM_NOSCAN:
        continue;
      case NODE_RECLAIM_FULL:
        continue;
      default:
        if (zone_watermark_ok(zone, order, mark, ac_classzone_idx(ac), alloc_flags))
          goto try_this_zone;

        continue;
      }
    }
    
try_this_zone: //本zone正常水位
    page = rmqueue(ac->preferred_zoneref->zone, zone, order, gfp_mask, alloc_flags, ac->migratetype);
  }
  
  return NULL;
}

可以看到在进行伙伴算法分配前有个关于水位的判断,今天我们就看下水位的概念。

简单的说在使用分区页面分配器中会将可以用的free pages与zone里的水位(watermark)进行比较。

水位初始化

代码语言:javascript
复制
int __meminit init_per_zone_wmark_min(void)
{
 unsigned long lowmem_kbytes;
 int new_min_free_kbytes;
 
 //nr_free_buffer_pages是获取ZONE_DMA和ZONE_NORMAL区中高于high水位的总页数nr_free_buffer_pages = managed_pages - high_pages
 lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
 new_min_free_kbytes = int_sqrt(lowmem_kbytes * 16);

 if (new_min_free_kbytes > user_min_free_kbytes) {
  min_free_kbytes = new_min_free_kbytes;
  //min的值必须在128kib-65536kib之间
  if (min_free_kbytes < 128)
   min_free_kbytes = 128;
  if (min_free_kbytes > 65536)
   min_free_kbytes = 65536;
 } else {
  pr_warn("min_free_kbytes is not updated to %d because user defined value %d is preferred\n",
    new_min_free_kbytes, user_min_free_kbytes);
 }
 //得到总的min后,就可以根据各个zone在总内存中的占比,通过do_div计算出他们各自的min值。
 setup_per_zone_wmarks();
 refresh_zone_stat_thresholds();
 setup_per_zone_lowmem_reserve();

 return 0;
}
  • nr_free_buffer_pages 是获取ZONE_DMA和ZONE_NORMAL区中高于high水位的总页数nr_free_buffer_pages = managed_pages - high_pages
  • min_free_kbytes 是总的min大小,min_free_kbytes = 4 * sqrt(lowmem_kbytes)
  • setup_per_zone_wmarks 根据总的min值,再加上各个zone在总内存中的占比,然后通过do_div就计算出他们各自的min值,进而计算出各个zone的水位大小。min,low,high的关系如下:low = min *125%; high = min * 150% min:low:high = 4:5:6
  • setup_per_zone_lowmem_reserve 当从Normal失败后,会尝试从DMA申请分配,通过lowmem_reserve[DMA],限制来自Normal的分配请求。其值可以通过/proc/sys/vm/lowmem_reserve_ratio来修改。

从这张图可以看出:

  • 如果空闲页数目min值,则该zone非常缺页,页面回收压力很大,应用程序写内存操作就会被阻塞,直接在应用程序的进程上下文中进行回收,即direct reclaim。
  • 如果空闲页数目小于low值,kswapd线程将被唤醒,并开始释放回收页面。
  • 如果空闲页面的值大于high值,则该zone的状态很完美, kswapd线程将重新休眠。

安卓系统中对水位的调节

为了避免direct reclaim,我们需要空余的内存大小一直保持在min值以上。但安卓这种大量用户操作网络接收的系统中,难免会遇到数据量突然增大,需要临时申请大量的内存,此时有可能kswapd回收的内存速度小于内存分配的速度,即发生direct reclaim,从而阻塞应用严重影响性能。

我们知道在内存分配时,只有low和min之间的区域才是kswapd活动的区域。而linux中默认的low与min之间的值又比较小,所以就很容易造成direct reclaim的情况。

「extra_free_kbytes」:

源于此,安卓在linux水位的基础上增加了extra_free_kbytes的变量,这个extra时额外加在low和min之间的,它在min不变的情况下,让low值有所增大。

源码如下:

代码语言:javascript
复制
static void __setup_per_zone_wmarks(void)
{
 unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
 unsigned long pages_low = extra_free_kbytes >> (PAGE_SHIFT - 10);
 
 ......
 
 for_each_zone(zone) {
  ......
  do_div(min, lowmem_pages);
  ......
 }

 calculate_totalreserve_pages();
}

想要知道extra_free_kbytes的引入是否取得效果,可以通过/proc/vmstat中的pageoutrun和allocstall来看,两者分别代表了kswapd和direct reclaim启动的次数。

「watermark_scale_factor」:

内核总是在进步的,在linux内核4.6版本中,又诞生了一种新的调节水位的方式,即watermark_scale_factor系数,其默认值是10,对应内存占比10/10000=0.1%,可通过/proc/sys/vm/watermark_scale_factor设置,最大值是1000。举个例子:当其被设为1000时,意味着min与low之间的差值,low与high之间的差值都将是内存大小的10%(1000/10000)。

前面讲的extra_free_kbytes的方式只增大了min和low之间的差值,而watermark_scale_factor则同时增大了min和low,low和high之间的差值。

至此,页框分配器中的快速分配方式已经结束,下一篇让我们进入页框分配器的慢速分配方式:__alloc_pages_slowpath,涉及到内存碎片的整理和内存回收。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人人都是极客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 水位初始化
  • 安卓系统中对水位的调节
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档