溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux分區(qū)頁框分配器的水位怎么理解

發(fā)布時(shí)間:2021-12-17 10:01:27 來源:億速云 閱讀:191 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“Linux分區(qū)頁框分配器的水位怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Linux分區(qū)頁框分配器的水位怎么理解”吧!

先來看下:

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;
}
 

可以看到在進(jìn)行伙伴算法分配前有個(gè)關(guān)于水位的判斷,今天我們就看下水位的概念。

簡單的說在使用分區(qū)頁面分配器中會將可以用的free pages與zone里的水位(watermark)進(jìn)行比較。

 

水位初始化

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區(qū)中高于high水位的總頁數(shù)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后,就可以根據(jù)各個(gè)zone在總內(nèi)存中的占比,通過do_div計(jì)算出他們各自的min值。
 setup_per_zone_wmarks();
 refresh_zone_stat_thresholds();
 setup_per_zone_lowmem_reserve();

 return 0;
}
 
  • nr_free_buffer_pages 是獲取ZONE_DMA和ZONE_NORMAL區(qū)中高于high水位的總頁數(shù)nr_free_buffer_pages = managed_pages - high_pages

  • min_free_kbytes 是總的min大小,min_free_kbytes = 4 * sqrt(lowmem_kbytes)

  • setup_per_zone_wmarks 根據(jù)總的min值,再加上各個(gè)zone在總內(nèi)存中的占比,然后通過do_div就計(jì)算出他們各自的min值,進(jìn)而計(jì)算出各個(gè)zone的水位大小。min,low,high的關(guān)系如下:low = min *125%;

    high = min * 150%

    min:low:high = 4:5:6

  • setup_per_zone_lowmem_reserve 當(dāng)從Normal失敗后,會嘗試從DMA申請分配,通過lowmem_reserve[DMA],限制來自Normal的分配請求。其值可以通過/proc/sys/vm/lowmem_reserve_ratio來修改。

Linux分區(qū)頁框分配器的水位怎么理解  

從這張圖可以看出:

  • 如果空閑頁數(shù)目min值,則該zone非常缺頁,頁面回收壓力很大,應(yīng)用程序?qū)憙?nèi)存操作就會被阻塞,直接在應(yīng)用程序的進(jìn)程上下文中進(jìn)行回收,即direct reclaim。
  • 如果空閑頁數(shù)目小于low值,kswapd線程將被喚醒,并開始釋放回收頁面。
  • 如果空閑頁面的值大于high值,則該zone的狀態(tài)很完美, kswapd線程將重新休眠。
 

安卓系統(tǒng)中對水位的調(diào)節(jié)

為了避免direct reclaim,我們需要空余的內(nèi)存大小一直保持在min值以上。但安卓這種大量用戶操作網(wǎng)絡(luò)接收的系統(tǒng)中,難免會遇到數(shù)據(jù)量突然增大,需要臨時(shí)申請大量的內(nèi)存,此時(shí)有可能kswapd回收的內(nèi)存速度小于內(nèi)存分配的速度,即發(fā)生direct reclaim,從而阻塞應(yīng)用嚴(yán)重影響性能。

我們知道在內(nèi)存分配時(shí),只有l(wèi)ow和min之間的區(qū)域才是kswapd活動的區(qū)域。而linux中默認(rèn)的low與min之間的值又比較小,所以就很容易造成direct reclaim的情況。

「extra_free_kbytes」:

源于此,安卓在linux水位的基礎(chǔ)上增加了extra_free_kbytes的變量,這個(gè)extra時(shí)額外加在low和min之間的,它在min不變的情況下,讓low值有所增大。

源碼如下:

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啟動的次數(shù)。

Linux分區(qū)頁框分配器的水位怎么理解

「watermark_scale_factor」:

內(nèi)核總是在進(jìn)步的,在linux內(nèi)核4.6版本中,又誕生了一種新的調(diào)節(jié)水位的方式,即watermark_scale_factor系數(shù),其默認(rèn)值是10,對應(yīng)內(nèi)存占比10/10000=0.1%,可通過/proc/sys/vm/watermark_scale_factor設(shè)置,最大值是1000。舉個(gè)例子:當(dāng)其被設(shè)為1000時(shí),意味著min與low之間的差值,low與high之間的差值都將是內(nèi)存大小的10%(1000/10000)。

前面講的extra_free_kbytes的方式只增大了min和low之間的差值,而watermark_scale_factor則同時(shí)增大了min和low,low和high之間的差值。

到此,相信大家對“Linux分區(qū)頁框分配器的水位怎么理解”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI