【原創】(十六)Linux記憶體管理之CMA

来源:https://www.cnblogs.com/LoyenWang/archive/2020/01/12/12182594.html
-Advertisement-
Play Games

背景 By 魯迅 By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex A53,雙核 3. 使用工具:Source Insight 3.5, Visio 1. 概述 ,連續記憶體分配器,用於分配連續的大塊記憶體。 ,會Reserve一片物理記憶體區域: 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. 概述

Contiguous Memory Allocator, CMA,連續記憶體分配器,用於分配連續的大塊記憶體。
CMA分配器,會Reserve一片物理記憶體區域:

  1. 設備驅動不用時,記憶體管理系統將該區域用於分配和管理可移動類型頁面;
  2. 設備驅動使用時,用於連續記憶體分配,此時已經分配的頁面需要進行遷移;

此外,CMA分配器還可以與DMA子系統集成在一起,使用DMA的設備驅動程式無需使用單獨的CMA API

2. 數據結構

內核定義了struct cma結構,用於管理一個CMA區域,此外還定義了全局的cma數組,如下:

struct cma {
    unsigned long   base_pfn;
    unsigned long   count;
    unsigned long   *bitmap;
    unsigned int order_per_bit; /* Order of pages represented by one bit */
    struct mutex    lock;
#ifdef CONFIG_CMA_DEBUGFS
    struct hlist_head mem_head;
    spinlock_t mem_head_lock;
#endif
    const char *name;
};

extern struct cma cma_areas[MAX_CMA_AREAS];
extern unsigned cma_area_count;
  • base_pfn:CMA區域物理地址的起始頁幀號;
  • count:CMA區域總體的頁數;
  • *bitmap:點陣圖,用於描述頁的分配情況;
  • order_per_bit:點陣圖中每個bit描述的物理頁面的order值,其中頁面數為2^order值;

來一張圖就會清晰明瞭:

3. 流程分析

3.1 CMA區域創建

3.1.1 方式一 根據dts來配置

之前的文章也都分析過,物理記憶體的描述放置在dts中,最終會在系統啟動過程中,對dtb文件進行解析,從而完成記憶體信息註冊。

CMA的記憶體在dts中的描述示例如下圖:

dtb解析過程中,會調用到rmem_cma_setup函數:

RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);

3.1.2 方式二 根據參數或巨集配置

可以通過內核參數或配置巨集,來進行CMA區域的創建,最終會調用到cma_declare_contiguous函數,如下圖:

3.2 CMA添加到Buddy System

在創建完CMA區域後,該記憶體區域成了保留區域,如果單純給驅動使用,顯然會造成記憶體的浪費,因此記憶體管理模塊會將CMA區域添加到Buddy System中,用於可移動頁面的分配和管理。CMA區域是通過cma_init_reserved_areas介面來添加到Buddy System中的。

core_initcall(cma_init_reserved_areas);

core_initcall巨集將cma_init_reserved_areas函數放置到特定的段中,在系統啟動的時候會調用到該函數。

3.3 CMA分配/釋放

  • CMA分配,入口函數為cma_alloc

  • CMA釋放,入口函數為cma_release
    函數比較簡單,直接貼上代碼
/**
 * cma_release() - release allocated pages
 * @cma:   Contiguous memory region for which the allocation is performed.
 * @pages: Allocated pages.
 * @count: Number of allocated pages.
 *
 * This function releases memory allocated by alloc_cma().
 * It returns false when provided pages do not belong to contiguous area and
 * true otherwise.
 */
bool cma_release(struct cma *cma, const struct page *pages, unsigned int count)
{
    unsigned long pfn;

    if (!cma || !pages)
        return false;

    pr_debug("%s(page %p)\n", __func__, (void *)pages);

    pfn = page_to_pfn(pages);

    if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
        return false;

    VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);

    free_contig_range(pfn, count);
    cma_clear_bitmap(cma, pfn, count);
    trace_cma_release(pfn, pages, count);

    return true;
}

3.4 DMA使用

代碼參考driver/base/dma-contiguous.c,主要包括的介面有:

/**
 * dma_alloc_from_contiguous() - allocate pages from contiguous area
 * @dev:   Pointer to device for which the allocation is performed.
 * @count: Requested number of pages.
 * @align: Requested alignment of pages (in PAGE_SIZE order).
 * @gfp_mask: GFP flags to use for this allocation.
 *
 * This function allocates memory buffer for specified device. It uses
 * device specific contiguous memory area if available or the default
 * global one. Requires architecture specific dev_get_cma_area() helper
 * function.
 */
struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                       unsigned int align, gfp_t gfp_mask);
 
 /**
 * dma_release_from_contiguous() - release allocated pages
 * @dev:   Pointer to device for which the pages were allocated.
 * @pages: Allocated pages.
 * @count: Number of allocated pages.
 *
 * This function releases memory allocated by dma_alloc_from_contiguous().
 * It returns false when provided pages do not belong to contiguous area and
 * true otherwise.
 */
bool dma_release_from_contiguous(struct device *dev, struct page *pages,
                 int count);

在上述的介面中,實際調用的就是cma_alloc/cma_release介面來實現的。

整體來看,CMA分配器還是比較簡單易懂,也不再深入分析。

4.後記

記憶體管理的分析先告一段落,後續可能還會針對某些模塊進一步的研究與完善。
記憶體管理子系統,極其複雜,盤根錯節,很容易就懵圈了,儘管費了不少心力,也只能說略知皮毛。
學習就像是爬山,面對一座高山,可能會有心理障礙,但是當你跨越之後,再看到同樣高的山,心理上你將不再畏懼。

接下來將研究進程管理子系統,將任督二脈打通。

未來會持續分析內核中的各類框架,併發機制等,敬請關註,一起探討。


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

-Advertisement-
Play Games
更多相關文章
  • 前言:當WPF項目後臺完成到一定程度的時候,就可以對XAML前端進行美化啦,個人認為XAML前端還是挺有意思的。 下麵舉一個Button加過小圖標後的例子: 是不是比生硬的文字看來更人性化了呢? 不多bb下麵開始講如何實現: 首先把你的圖標圖片文件放入項目,我的存放的是項目的根目錄的Images文件 ...
  • 之前多次安裝MongoDB失敗,今天終於配置安裝成功了!!! 首先,介紹一下:MongoDB是一個基於分散式文件存儲的NoSQL資料庫。由 C++ 語言編寫。旨在為 WEB 應用提供可擴展的高性能數據存儲解決方案。 MongoDB的主要目標是在鍵/值存儲方式(提供了高性能和高度伸縮性)以及傳統的RD ...
  • 前提 cat命令是用於連接文件並輸出到標準輸出設備或指定文件中。 EOF為標誌,可以替換為其他字元串 代碼塊 將文件內容作為標準輸出也就是將文件內容輸出到屏幕中,也可寫作 cat filename cat filename 創建文件,將2個EOF中的字元串作為標準輸入輸出到filename文件中 c ...
  • 前提 AWK是一種處理文本文件的語言,是一個強大的文本分析工具。 本文將使用命令awk將具有某個關鍵字的段落提取出來。 準備數據 段落提取 假設我們需要的關鍵字為 nid=0x63ef ...
  • 部署圖書管理系統項目 部署準備 部署圖書管理項目你將使用以下軟體 nginx uWSGI CentOS7 部署圖書管理項目文件 virtualenv supervisor WSGI、uWSGI python web伺服器開發使用WSGI協議(Web Server Gateway Interface) ...
  • ArchLinux下electronssr無法啟動的解決措施 今天重新配置electron ssr時發現閃退(無法啟動)。 於是開始查錯 首先是找到了目錄位置 /usr/electron ssr/electron ssr 並且嘗試在終端里啟動它。 發現缺少 python2 , 安裝 python2 ...
  • 最近在滴滴雲上看到伺服器很便宜,1核2G,1年只需要68塊錢。下麵是我基於Docker部署Javaweb服務的過程。目前我見過的最便宜的伺服器,阿裡雲打折的時候都沒有這麼便宜啊,果斷入手。有需要的話可以通過下麵鏈接購買。 滴滴雲全線標準型雲伺服器限時特惠,新購雲服務包1個月5折,包3個月4折,包6個 ...
  • 部署gitlab 1、配置倉庫源 # vim /etc/apt/sources.listdeb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb-src http://mirrors.al ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...