【Linux 内核 内存管理】物理分配页 ⑧ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 获取首选内存区域 | 异步回收内存页 | 最低水线也分配 | 直接分配 )
文章目錄
- 一、獲取首選內存區域
- 二、異步回收內存頁
- 三、最低水線也分配
- 四、直接分配內存
在 【Linux 內核 內存管理】物理分配頁 ② ( __alloc_pages_nodemask 函數參數分析 | __alloc_pages_nodemask 函數分配物理頁流程 ) 博客中 , 分析了 __alloc_pages_nodemask 函數分配物理頁流程如下 :
首先 , 根據 gfp_t gfp_mask 分配標志位 參數 , 得到 " 內存節點 “ 的 首選 ” 區域類型 " 和 " 遷移類型 " ;
然后 , 執行 " 快速路徑 " , 第一次分配 嘗試使用 低水線分配 ;
如果上述 " 快速路徑 " 分配失敗 , 則執行 " 慢速路徑 " 分配 ;
上述涉及到了 " 快速路徑 " 和 " 慢速路徑 " 222 種物理頁分配方式 ;
繼續接著上一篇博客 【Linux 內核 內存管理】物理分配頁 ⑦ ( __alloc_pages_slowpath 慢速路徑調用函數源碼分析 | 判斷頁階數 | 讀取 mems_allowed | 分配標志位轉換 ) 分析 __alloc_pages_slowpath 慢速路徑 內存分配 調用函數 的后續部分源碼 ;
一、獲取首選內存區域
獲取 " 首選內存區域 " , 如果獲取失敗 , 則 goto 跳轉到 nopage 標號位置運行后續代碼 ;
/** We need to recalculate the starting point for the zonelist iterator* because we might have used different nodemask in the fast path, or* there was a cpuset modification and we are retrying - otherwise we* could end up iterating over non-eligible zones endlessly.*/ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,ac->high_zoneidx, ac->nodemask);if (!ac->preferred_zoneref->zone)goto nopage;源碼路徑 : linux-4.12\mm\page_alloc.c#3731
二、異步回收內存頁
調用 wake_all_kswapds 函數 , 異步 回收 物理內存頁 ,
這里的異步 是通過 喚醒 " 回收線程 " 進行回收內存頁的 ;
if (gfp_mask & __GFP_KSWAPD_RECLAIM)wake_all_kswapds(order, ac);源碼路徑 : linux-4.12\mm\page_alloc.c#3736
三、最低水線也分配
調用 get_page_from_freelist 函數 , 使用 " 最低水線 " 進行物理頁分配 ,
如果處理成功 , 則跳轉到 got_pg 標號處執行 ;
/** The adjusted alloc_flags might result in immediate success, so try* that first*/page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);if (page)goto got_pg;源碼路徑 : linux-4.12\mm\page_alloc.c#3743
四、直接分配內存
申請 物理頁 內存 的階數 , 滿足以下 333 個條件 :
can_direct_reclaim
(costly_order || (order > 0 && ac->migratetype != MIGRATE_MOVABLE))
!gfp_pfmemalloc_allowed(gfp_mask)
執行該分支 " 直接分配內存 " 操作 ;
/** For costly allocations, try direct compaction first, as it's likely* that we have enough base pages and don't need to reclaim. For non-* movable high-order allocations, do that as well, as compaction will* try prevent permanent fragmentation by migrating from blocks of the* same migratetype.* Don't try this for allocations that are allowed to ignore* watermarks, as the ALLOC_NO_WATERMARKS attempt didn't yet happen.*/if (can_direct_reclaim &&(costly_order ||(order > 0 && ac->migratetype != MIGRATE_MOVABLE))&& !gfp_pfmemalloc_allowed(gfp_mask)) {page = __alloc_pages_direct_compact(gfp_mask, order,alloc_flags, ac,INIT_COMPACT_PRIORITY,&compact_result);if (page)goto got_pg;/** Checks for costly allocations with __GFP_NORETRY, which* includes THP page fault allocations*/if (costly_order && (gfp_mask & __GFP_NORETRY)) {/** If compaction is deferred for high-order allocations,* it is because sync compaction recently failed. If* this is the case and the caller requested a THP* allocation, we do not want to heavily disrupt the* system, so we fail the allocation instead of entering* direct reclaim.*/if (compact_result == COMPACT_DEFERRED)goto nopage;/** Looks like reclaim/compaction is worth trying, but* sync compaction could be very expensive, so keep* using async compaction.*/compact_priority = INIT_COMPACT_PRIORITY;}}源碼路徑 : linux-4.12\mm\page_alloc.c#3756
總結
以上是生活随笔為你收集整理的【Linux 内核 内存管理】物理分配页 ⑧ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 获取首选内存区域 | 异步回收内存页 | 最低水线也分配 | 直接分配 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SDK无法下载Package的提示 Do
- 下一篇: Xcode操作流