【原創】(十五)Linux記憶體管理之RMAP

来源:https://www.cnblogs.com/LoyenWang/archive/2020/01/08/12164683.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. 概述

RMAP反向映射是一種物理地址反向映射虛擬地址的方法。

  • 映射
    頁表用於虛擬地址到物理地址映射,其中的PTE頁表項記錄了映射關係,同時struct page結構體中的mapcount欄位保存了有多少PTE頁表項映射了該物理頁。

  • 反向映射
    當某個物理地址要進行回收或遷移時,此時需要去找到有多少虛擬地址射在該物理地址,並斷開映射處理。在沒有反向映射的機制時,需要去遍歷進程的頁表,這個效率顯然是很低下的。反向映射可以找到虛擬地址空間VMA,並僅從VMA使用的用戶頁表中取消映射,可以快速解決這個問題。

反向映射的典型應用場景:

  1. kswapd進行頁面回收時,需要斷開所有映射了該匿名頁面的PTE表項;
  2. 頁面遷移時,需要斷開所有映射了該匿名頁面的PTE表項;

2. 數據結構

反向映射有三個關鍵的結構體:

  1. struct vm_area_struct,簡稱VMA;
    VMA我們在之前的文章中介紹過,用於描述進程地址空間中的一段區域。與反向映射相關的欄位如下:
struct vm_area_struct {
...
/*
     * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
     * list, after a COW of one of the file pages.  A MAP_SHARED vma
     * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
     * or brk vma (with NULL file) can only be in an anon_vma list.
     */
    struct list_head anon_vma_chain; /* Serialized by mmap_sem &
                      * page_table_lock */
    struct anon_vma *anon_vma;  /* Serialized by page_table_lock */
...
}
  1. struct anon_vma,簡稱AV;
    AV結構用於管理匿名類型VMAs,當有匿名頁需要unmap處理時,可以先找到AV,然後再通過AV進行查找處理。結構如下:
/*
 * The anon_vma heads a list of private "related" vmas, to scan if
 * an anonymous page pointing to this anon_vma needs to be unmapped:
 * the vmas on the list will be related by forking, or by splitting.
 *
 * Since vmas come and go as they are split and merged (particularly
 * in mprotect), the mapping field of an anonymous page cannot point
 * directly to a vma: instead it points to an anon_vma, on whose list
 * the related vmas can be easily linked or unlinked.
 *
 * After unlinking the last vma on the list, we must garbage collect
 * the anon_vma object itself: we're guaranteed no page can be
 * pointing to this anon_vma once its vma list is empty.
 */
struct anon_vma {
    struct anon_vma *root;      /* Root of this anon_vma tree */
    struct rw_semaphore rwsem;  /* W: modification, R: walking the list */
    /*
     * The refcount is taken on an anon_vma when there is no
     * guarantee that the vma of page tables will exist for
     * the duration of the operation. A caller that takes
     * the reference is responsible for clearing up the
     * anon_vma if they are the last user on release
     */
    atomic_t refcount;

    /*
     * Count of child anon_vmas and VMAs which points to this anon_vma.
     *
     * This counter is used for making decision about reusing anon_vma
     * instead of forking new one. See comments in function anon_vma_clone.
     */
    unsigned degree;

    struct anon_vma *parent;    /* Parent of this anon_vma */

    /*
     * NOTE: the LSB of the rb_root.rb_node is set by
     * mm_take_all_locks() _after_ taking the above lock. So the
     * rb_root must only be read/written after taking the above lock
     * to be sure to see a valid next pointer. The LSB bit itself
     * is serialized by a system wide lock only visible to
     * mm_take_all_locks() (mm_all_locks_mutex).
     */

    /* Interval tree of private "related" vmas */
    struct rb_root_cached rb_root;
};
  1. struct anon_vma_chain,簡稱AVC;
    AVC是連接VMAAV之間的橋梁。
/*
 * The copy-on-write semantics of fork mean that an anon_vma
 * can become associated with multiple processes. Furthermore,
 * each child process will have its own anon_vma, where new
 * pages for that process are instantiated.
 *
 * This structure allows us to find the anon_vmas associated
 * with a VMA, or the VMAs associated with an anon_vma.
 * The "same_vma" list contains the anon_vma_chains linking
 * all the anon_vmas associated with this VMA.
 * The "rb" field indexes on an interval tree the anon_vma_chains
 * which link all the VMAs associated with this anon_vma.
 */
struct anon_vma_chain {
    struct vm_area_struct *vma;
    struct anon_vma *anon_vma;
    struct list_head same_vma;   /* locked by mmap_sem & page_table_lock */
    struct rb_node rb;          /* locked by anon_vma->rwsem */
    unsigned long rb_subtree_last;
#ifdef CONFIG_DEBUG_VM_RB
    unsigned long cached_vma_start, cached_vma_last;
#endif
};

來一張圖就清晰明瞭了:

  • 通過same_vma鏈表節點,將anon_vma_chain添加到vma->anon_vma_chain鏈表中;
  • 通過rb紅黑樹節點,將anon_vma_chain添加到anon_vma->rb_root的紅黑樹中;

2. 流程分析

先看一下巨集觀的圖:

  • 地址空間VMA可以通過頁表完成虛擬地址到物理地址的映射;
  • 頁框與page結構對應,page結構中的mapping欄位指向anon_vma,從而可以通過RMAP機制去找到與之關聯的VMA

2.1 anon_vma_prepare

之前在page fault的文章中,提到過anon_vma_prepare函數,這個函數完成的工作就是為進程地址空間中的VMA準備struct anon_vma結構。

調用常式及函數流程如下圖所示:

至於VMA,AV,AVC三者之間的關聯關係,在上文的圖中已經有所描述。

當創建了與VMA關聯的AV後,還有關鍵的一步需要做完,才能算是真正的把RMAP通路打通,那就是讓pageAV關聯起來。只有這樣才能通過page找到AV,進而找到VMA,從而完成對應的PTE unmap操作。

2.2 子進程創建anon_vma

父進程通過fork()來創建子進程,子進程會複製整個父進程的地址空間及頁表。子進程拷貝了父進程的VMA數據結構內容,而子進程創建相應的anon_vma結構,是通過anon_vma_fork()函數來實現的。

anon_vma_fork()效果圖如下:

以實際fork()兩次為例,發生COW之後,看看三個進程的鏈接關係,如下圖:

2.3 TTU(try to unmap)Rmap Walk

如果有page被映射到多個虛擬地址,可以通過Rmap Walk機制來遍歷所有的VMA,並最終調用回調函數來取消映射。

與之相關的結構體為struct rmap_walk_control,如下:

/*
 * rmap_walk_control: To control rmap traversing for specific needs
 *
 * arg: passed to rmap_one() and invalid_vma()
 * rmap_one: executed on each vma where page is mapped
 * done: for checking traversing termination condition
 * anon_lock: for getting anon_lock by optimized way rather than default
 * invalid_vma: for skipping uninterested vma
 */
struct rmap_walk_control {
    void *arg;
    /*
     * Return false if page table scanning in rmap_walk should be stopped.
     * Otherwise, return true.
     */
    bool (*rmap_one)(struct page *page, struct vm_area_struct *vma,
                    unsigned long addr, void *arg);
    int (*done)(struct page *page);
    struct anon_vma *(*anon_lock)(struct page *page);
    bool (*invalid_vma)(struct vm_area_struct *vma, void *arg);
};

取消映射的入口為try_to_unmap,流程如下圖所示:

基本的套路就是圍繞著struct rmap_walk_control結構,初始化回調函數,以便在適當的時候能調用到。

關於取消映射try_to_unmap_one的詳細細節就不進一步深入了,把握好大體框架即可。


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

-Advertisement-
Play Games
更多相關文章
  • STM32F103是一款高性價比、多功能的單片機,配備常用的32位單片機片外資源,基於ARM Cortex-M3的32位處理器晶元,片內具有256KB FLASH,48KB RAM ( 片上集成12Bit A/D、D/A、PWM、CAN、USB、SDIO、FSMC等資源)。是應用的較為廣泛的一款單片 ...
  • 1、man find 解釋: find - search for files in a directory hierarchy,即:在目錄下查找文件 2、按文件被修改的時間查詢文件 命令格式: find 目錄 -mtime +n -name 文件名 在指定目錄及其子目錄下查找(負無窮,nowTime ...
  • 最近windows上需要配置全局代理 走 socks5,發現同類型的有 cow pcap 等解決方案,通過嘗試發現還是proxifier 比較好用! 下載:https://www.proxifier.com/download/legacy/ProxifierSetup331.exe 註冊: 激活ke ...
  • 安裝IIS7 1、打開伺服器管理器(開始-電腦-右鍵-管理-也可以打開),添加角色 直接下一步 勾選Web伺服器(IIS),下一步,有個註意事項繼續下一步(這裡我就不截圖了) 勾選ASP.NET會彈出以下視窗添加所需的角色服務,勾選CGI(這裡根據個人情況勾選,CGI是必選的,否則PHP不生效的) ...
  • 一、原理 1、Hypervisor是一種運行在物理伺服器和操作系統之間的中間軟體層,可允許多個操作系統和應用共用一套基礎物理硬體,它能直接訪問物理設備,會給每一臺虛擬機分配記憶體、CPU、網路、磁碟等資源,也可以確保虛擬機對應的硬體資源不被其他虛擬機訪問,是所有虛擬化技術的核心。 2、虛擬機 指通過軟 ...
  • 關於日誌切割 日誌文件包含了關於系統中發生的事件的有用信息,在排障過程中或者系統性能分析時經常被用到。對於忙碌的伺服器,日誌文件大小會增長極快,伺服器會很快消耗磁碟空間,這成了個問題。除此之外,處理一個單個的龐大日誌文件也常常是件十分棘手的事。logrotate是個十分有用的工具,它可以自動對日誌進 ...
  • test簡介 測試命令test用於形成一個表達式,結合條件判斷語句if-else來判斷。 例如可以判斷某個文件是否存在,是否具備什麼樣的特性(可讀嗎?可寫嗎?可執行嗎?塊文件嗎?)等等。 測試命令test有三種語法格式: test EXPRESSION [ EXPRESSION ] [[ EXPRE ...
  • Delete ms-resource:AppName/Text ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...