【原創】(九)Linux記憶體管理 - zoned page frame allocator - 4

来源:https://www.cnblogs.com/LoyenWang/archive/2019/10/27/11746357.html
-Advertisement-
Play Games

背景 By 魯迅 By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex A53,雙核 3. 使用工具:Source Insight 3.5, Visio 1. 概述 本文將描述 ,記憶體碎片整理技術。 記憶體碎片分為內碎片和外碎片: 內碎片:記憶體頁裡邊的碎片; 外 ...


背景

  • Read the fucking source code! --By 魯迅
  • A picture is worth a thousand words. --By 高爾基

說明:

  1. Kernel版本:4.14
  2. ARM64處理器,Contex-A53,雙核
  3. 使用工具: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的時候,維護兩個掃描器,對應freepagesmigratepages,最終將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

  1. 在記憶體分配過程中,由於分配請求不能滿足,直接觸發記憶體compact處理;
  2. 在沒有足夠記憶體的情況下,kcompactd守護線程在後臺喚醒,執行compact處理;
  3. 手動觸發,通過echo 1 > /proc/sys/vm/compact_memory來觸發;

圖來了:

實際操作一把:
cat /proc/pagetypeinfo如下圖:

3. compact處理

這個處理的過程還是很複雜的,下圖顯示了大概的過程:

下邊將針對各個子模塊更深入點分析。

  • compaction_suitable

判斷是否執行記憶體的碎片整理,需要滿足以下三個條件:

  1. 除去申請的頁面,空閑頁面數將低於水印值,或者雖然大於等於水印值,但是沒有一個足夠大的空閑頁塊;
  2. 空閑頁面減去兩倍的申請頁面(兩倍表明有足夠多的的空閑頁面作為遷移目標),高於水印值;
  3. 申請的order大於PAGE_ALLOC_COSTLY_ORDER時,計算碎片指數fragindex,根據值來判斷;
  • isolate_migratepages
    isolate_migratepages函數中,遷移掃描器以pageblock為單位,掃描可移動頁,最終把可移動的頁添加到struct compact_control結構中的migratepages鏈表中。如下圖所示:

isolate_freepages的邏輯與isolate_migratepages類似,也是對頁進行隔離處理,最終添加cc->freepages鏈表中。

當空閑掃描器和遷移掃描器完成掃描之後,那就是時候將兩個鏈表中的頁做一下migrate操作了。

  • migrate_pages
  1. 調用compact_alloc函數,從cc->freepages鏈表中取出一個空閑頁;
  2. 調用__unmap_and_move來把可移動頁移動到空閑頁處;
    _unmap_and_move函數涉及到反向映射,以及頁緩存等,留在以後再深入看。這個函數兩個關鍵作用:1)調用try_to_unmap刪除進程頁表中舊的映射關係,在需要訪問的時候再重新映射到新的物理地址上;2)調用move_to_new_page函數將舊頁移動到新的物理頁上,其中在彙編文件arch/arm64/lib/copy_page.Scopy_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值
...
};


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、簡介 foreach迴圈可以迭代數組或者一個集合對象 二、語法 foreach(數據類型 變數名 in 數組名) { //語句塊; } 迴圈運行的過程:每一次迴圈時,從集合中取出一個新的元素值。放到只讀變數中去,如果括弧中的整個表達式返回值為 true,foreach 塊中的語句就能夠執行。 一 ...
  • 在開發過程中,我們經常會遇到對業務數據進行模糊搜索的需求,例如電商網站對於商品的搜索,以及內容網站對於內容的關鍵字檢索等等。對於這些高級的搜索功能,顯然資料庫的 Like 是不合適的,通常我們採用 ElasticSearch 來完成數據的搜索和分析,有了這個利器,我們可以輕鬆應對上述場景,實現關鍵字 ...
  • 一、簡介 一個for迴圈是一個允許所編寫一個執行特定次數的迴圈的重覆控制結構。 二、語法 for (表達式1; 表達式2; 表達式3) { 迴圈體; } 下麵是 for 迴圈的控制流: 表達式1會首先被執行,且只會執行一次。這一步允許您聲明並初始化任何迴圈控制變數。您也可以不在這裡寫任何語句,只要有 ...
  • 場景 Winform控制項-DevExpress18下載安裝註冊以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100061243 在上面已經實現DevExpress的安裝之後,拖拽一個TreeList,然後怎樣給 ...
  • Aspose.Words for C ++ 是一種高級Word文檔處理API,用於執行各種文檔處理任務。API直接在您自己的C ++應用程式中提供文檔格式化,操作,郵件合併,水印和更多功能,而無需Microsoft Word。API支持大多數Microsoft Word格式進行處理。 近期更新了As ...
  • 一、簡介 只要給定條件為true,C#的while迴圈語句會迴圈重新執行一個目標的語句。 二、語法 C# while的語法: while(迴圈條件) { 迴圈體; } 三、執行過程 程式運行到while處,首先判斷while所帶的小括弧內的迴圈條件是否成立,如果成立的話,也就是返回一個true,則執 ...
  • 比如獲取Button按鈕: System.Reflection.FieldInfo[] fieldInfo = form.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingF ...
  • 用慣了VM換BOX還是有點不大一樣的,比如複製 我用了2個網卡,所以看起來麻煩了一次 註釋了UUID 應該有更好的辦法來操作,下麵的看起來有點啰嗦,先湊合著這樣弄。。。 1、關機 2、複製 3、改名稱、新建路徑、MAC 4、完全複製 5、等待 6、啟動NEW機器 產生eth2和eth3兩塊新網卡,準 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...