【原創】(九)Linux記憶體管理 - zoned page frame allocator - 4
背景
Read the fucking source code!
--By 魯迅A picture is worth a thousand words.
--By 高爾基
說明:
- Kernel版本:4.14
- ARM64處理器,Contex-A53,雙核
- 使用工具:Source Insight 3.5, Visio
1. 概述
本文將描述memory compaction
,記憶體碎片整理技術。
記憶體碎片分為內碎片和外碎片:
- 內碎片:記憶體頁裡邊的碎片;
- 外碎片:記憶體頁之間的碎片,可能會造成連續物理頁面分配失敗。
memory compaction
就是通過將正在使用的可移動頁面遷移到另一個地方以獲得連續的空閒頁面的方法。針對記憶體碎片,核心中定義了migrate_type
MIGRATE_UNMOVABLE
:不可移動,對應於核心分配的頁面;MIGRATE_MOVABLE
:可移動,對應於從使用者空間分配的記憶體或檔案;MIGRATE_RECLAIMABLE
:不可移動,可以進行回收處理;
先來一張memory compaction
的概況圖:
上圖對應的是struct page
的操作,而針對實體記憶體的操作如下圖所示:
在之前的文章中提到過pageblock
,我們看到圖中zone
區域是以pageblock
為單位上下掃描的,pageblock
的大小定義如下(未使用huge table
情況下),與Buddy System管理中的最大塊大小一致:
/* If huge pages are not used, group by MAX_ORDER_NR_PAGES */
#define pageblock_order (MAX_ORDER-1)
#define pageblock_nr_pages (1UL << pageblock_order)
好了,已經有一個初步印象了,那就進一步的分析吧。
1. 資料結構
1.1 compact_priority
/* * Determines how hard direct compaction should try to succeed. * Lower value means higher priority, analogically to reclaim priority. */ enum compact_priority { COMPACT_PRIO_SYNC_FULL, MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_FULL, COMPACT_PRIO_SYNC_LIGHT, MIN_COMPACT_COSTLY_PRIORITY = COMPACT_PRIO_SYNC_LIGHT, DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT, COMPACT_PRIO_ASYNC, INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC };
本結構用於描述memory compact
的幾種不同方式:
COMPACT_PRIO_SYNC_FULL/MIN_COMPACT_PRIORITY
:最高優先順序,壓縮和遷移以同步的方式完成;COMPACT_PRIO_SYNC_LIGHT/MIN_COMPACT_COSTLY_PRIORITY/DEF_COMPACT_PRIORITY
:中優先順序,壓縮以同步方式處理,遷移以非同步方式處理;COMPACT_PRIO_ASYNC/INIT_COMPACT_PRIORITY
:最低優先順序,壓縮和遷移以非同步方式處理。
1.2 compact_result
本結構用於描述壓縮處理函式的返回值:
/* Return values for compact_zone() and try_to_compact_pages() */
/* When adding new states, please adjust include/trace/events/compaction.h */
enum compact_result {
/* For more detailed tracepoint output - internal to compaction */
COMPACT_NOT_SUITABLE_ZONE,
/*
* compaction didn't start as it was not possible or direct reclaim
* was more suitable
*/
COMPACT_SKIPPED,
/* compaction didn't start as it was deferred due to past failures */
COMPACT_DEFERRED,
/* compaction not active last round */
COMPACT_INACTIVE = COMPACT_DEFERRED,
/* For more detailed tracepoint output - internal to compaction */
COMPACT_NO_SUITABLE_PAGE,
/* compaction should continue to another pageblock */
COMPACT_CONTINUE,
/*
* The full zone was compacted scanned but wasn't successfull to compact
* suitable pages.
*/
COMPACT_COMPLETE,
/*
* direct compaction has scanned part of the zone but wasn't successfull
* to compact suitable pages.
*/
COMPACT_PARTIAL_SKIPPED,
/* compaction terminated prematurely due to lock contentions */
COMPACT_CONTENDED,
/*
* direct compaction terminated after concluding that the allocation
* should now succeed
*/
COMPACT_SUCCESS,
};
1.3 migrate_mode
本結構用於描述migrate
過程中的不同模式,主要針對同步和非同步的處理。
/*
* MIGRATE_ASYNC means never block
* MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
* on most operations but not ->writepage as the potential stall time
* is too significant
* MIGRATE_SYNC will block when migrating pages
* MIGRATE_SYNC_NO_COPY will block when migrating pages but will not copy pages
* with the CPU. Instead, page copy happens outside the migratepage()
* callback and is likely using a DMA engine. See migrate_vma() and HMM
* (mm/hmm.c) for users of this mode.
*/
enum migrate_mode {
MIGRATE_ASYNC,
MIGRATE_SYNC_LIGHT,
MIGRATE_SYNC,
MIGRATE_SYNC_NO_COPY,
};
1.4 compact_control
compact_control
結構體用於在執行compact
的時候,維護兩個掃描器,對應freepages
和migratepages
,最終將migratepages
中的頁拷貝到freepages
中去。具體的欄位註釋足夠詳盡,不細說了。
/*
* compact_control is used to track pages being migrated and the free pages
* they are being migrated to during memory compaction. The free_pfn starts
* at the end of a zone and migrate_pfn begins at the start. Movable pages
* are moved to the end of a zone during a compaction run and the run
* completes when free_pfn <= migrate_pfn
*/
struct compact_control {
struct list_head freepages; /* List of free pages to migrate to */
struct list_head migratepages; /* List of pages being migrated */
struct zone *zone;
unsigned long nr_freepages; /* Number of isolated free pages */
unsigned long nr_migratepages; /* Number of pages to migrate */
unsigned long total_migrate_scanned;
unsigned long total_free_scanned;
unsigned long free_pfn; /* isolate_freepages search base */
unsigned long migrate_pfn; /* isolate_migratepages search base */
unsigned long last_migrated_pfn;/* Not yet flushed page being freed */
const gfp_t gfp_mask; /* gfp mask of a direct compactor */
int order; /* order a direct compactor needs */
int migratetype; /* migratetype of direct compactor */
const unsigned int alloc_flags; /* alloc flags of a direct compactor */
const int classzone_idx; /* zone index of a direct compactor */
enum migrate_mode mode; /* Async or sync migration mode */
bool ignore_skip_hint; /* Scan blocks even if marked skip */
bool ignore_block_suitable; /* Scan blocks considered unsuitable */
bool direct_compaction; /* False from kcompactd or /proc/... */
bool whole_zone; /* Whole zone should/has been scanned */
bool contended; /* Signal lock or sched contention */
bool finishing_block; /* Finishing current pageblock */
};
2. 呼叫流程
光看上文的資料結構,會比較零散,看看整體的流程吧。
在核心中,有三種方式來操作memory compact
:
- 在記憶體分配過程中,由於分配請求不能滿足,直接觸發記憶體
compact
處理; - 在沒有足夠記憶體的情況下,
kcompactd
守護執行緒在後臺喚醒,執行compact
處理; - 手動觸發,通過
echo 1 > /proc/sys/vm/compact_memory
來觸發;
圖來了:
實際操作一把:
cat /proc/pagetypeinfo
如下圖:
3. compact
處理
這個處理的過程還是很複雜的,下圖顯示了大概的過程:
下邊將針對各個子模組更深入點分析。
compaction_suitable
判斷是否執行記憶體的碎片整理,需要滿足以下三個條件:
- 除去申請的頁面,空閒頁面數將低於水印值,或者雖然大於等於水印值,但是沒有一個足夠大的空閒頁塊;
- 空閒頁面減去兩倍的申請頁面(兩倍表明有足夠多的的空閒頁面作為遷移目標),高於水印值;
- 申請的
order
大於PAGE_ALLOC_COSTLY_ORDER
時,計算碎片指數fragindex
,根據值來判斷;
isolate_migratepages
isolate_migratepages
函式中,遷移掃描器以pageblock
為單位,掃描可移動頁,最終把可移動的頁新增到struct compact_control
結構中的migratepages
連結串列中。如下圖所示:
isolate_freepages
的邏輯與isolate_migratepages
類似,也是對頁進行隔離處理,最終新增cc->freepages
連結串列中。
當空閒掃描器和遷移掃描器完成掃描之後,那就是時候將兩個連結串列中的頁做一下migrate
操作了。
migrate_pages
- 呼叫
compact_alloc
函式,從cc->freepages
連結串列中取出一個空閒頁; - 呼叫
__unmap_and_move
來把可移動頁移動到空閒頁處;
_unmap_and_move
函式涉及到反向對映,以及頁快取等,留在以後再深入看。這個函式兩個關鍵作用:1)呼叫try_to_unmap
刪除程序頁表中舊的對映關係,在需要訪問的時候再重新對映到新的實體地址上;2)呼叫move_to_new_page
函式將舊頁移動到新的物理頁上,其中在彙編檔案arch/arm64/lib/copy_page.S
中copy_page
函式完成拷貝。
compact_finished
compact_finished
函式主要用於檢查compact
是否完成。
compaction_deferred/compaction_defer_reset/defer_compaction
上述這三個函式與記憶體碎片推遲compact
有關,這三個函式是在try_to_compact_pages
中呼叫。當free pages除去申請頁面數高於水位值,且申請或備用的遷移型別至少有一個足夠大的空閒頁面時,可以認為compact
成功。在沒有成功時,可能需要推遲幾次來處理。
struct zone
結構中與之有關的欄位如下:
struct zone {
...
/*
* On compaction failure, 1<<compact_defer_shift compactions
* are skipped before trying again. The number attempted since
* last failure is tracked with compact_considered.
*/
unsigned int compact_considered; //記錄推遲次數
unsigned int compact_defer_shift; //(1 << compact_defer_shift)=推遲次數,最大為6
int compact_order_failed; //記錄碎片整理失敗時的申請order值
...
};
相關推薦
【原創】(九)Linux記憶體管理 - zoned page frame allocator - 4
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(六)Linux記憶體管理 - zoned page frame allocator - 1
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(七)Linux記憶體管理 - zoned page frame allocator - 2
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(八)Linux記憶體管理 - zoned page frame allocator - 3
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十三)Linux記憶體管理之vma/malloc/mmap
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(四)Linux記憶體模型之Sparse Memory Model
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(三)Linux paging_init解析
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(一)Linux程序排程器-基礎
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(二)Linux程序排程器-CPU負載
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(三)Linux程序排程器-程序切換
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(四)Linux程序排程-組排程及頻寬控制
# 背景 - `Read the fucking source code!` --By 魯迅 - `A picture is worth a thousand words.` --By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex-A53,雙核 3. 使用工具:S
【原創】(五)Linux程序排程-CFS排程器
# 背景 - `Read the fucking source code!` --By 魯迅 - `A picture is worth a thousand words.` --By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex-A53,雙核 3. 使用工具:S
【原創】(六)Linux程序排程-實時排程器
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十四)Linux記憶體管理之page fault處理
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
(五)Linux記憶體管理zone_sizes_init
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十一)Linux記憶體管理slub分配器
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十二)Linux記憶體管理之vmap與vmalloc
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十五)Linux記憶體管理之RMAP
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【原創】(十六)Linux記憶體管理之CMA
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,
【ASP.NET Core快速入門】(九) RoutingMiddleware介紹以及MVC引入
pre configure onf mvc tin 常用 esp red 引入 前言 前面我們介紹了使用app.Map來配置路由,但是對於一般不是特別大的項目來說,我們不使用Map來進行路由配置。 配置路由 我們首先需要在Startup.cs文件中的Configu