本篇內容主要講解“Linux分區(qū)頁框分配器的水位怎么理解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Linux分區(qū)頁框分配器的水位怎么理解”吧!
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比樂都網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式樂都網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋樂都地區(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;
}
可以看到在進行伙伴算法分配前有個關于水位的判斷,今天我們就看下水位的概念。
簡單的說在使用分區(qū)頁面分配器中會將可以用的free pages與zone里的水位(watermark)進行比較。
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ù)各個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區(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值,再加上各個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來修改。
從這張圖可以看出:
為了避免direct reclaim,我們需要空余的內存大小一直保持在min值以上。但安卓這種大量用戶操作網(wǎng)絡接收的系統(tǒng)中,難免會遇到數(shù)據(jù)量突然增大,需要臨時申請大量的內存,此時有可能kswapd回收的內存速度小于內存分配的速度,即發(fā)生direct reclaim,從而阻塞應用嚴重影響性能。
我們知道在內存分配時,只有l(wèi)ow和min之間的區(qū)域才是kswapd活動的區(qū)域。而linux中默認的low與min之間的值又比較小,所以就很容易造成direct reclaim的情況。
「extra_free_kbytes」:
源于此,安卓在linux水位的基礎上增加了extra_free_kbytes的變量,這個extra時額外加在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ù)。
「watermark_scale_factor」:
內核總是在進步的,在linux內核4.6版本中,又誕生了一種新的調節(jié)水位的方式,即watermark_scale_factor系數(shù),其默認值是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之間的差值。
到此,相信大家對“Linux分區(qū)頁框分配器的水位怎么理解”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!