高端記憶體映射之kmap_atomic固定映射--Linux記憶體管理(二十一)

来源:https://www.cnblogs.com/linhaostudy/archive/2019/01/01/10206300.html
-Advertisement-
Play Games

1 固定映射 1.1 數據結構 linux高端記憶體中的臨時記憶體區為固定記憶體區的一部分, 對於固定記憶體在linux內核中有下麵描述 x86| arm| arm64 | | "arch/x86/include/asm/fixmap.h?v=4.7, line 67" | "arch/arm/includ ...


1 固定映射

1.1 數據結構

linux高端記憶體中的臨時記憶體區為固定記憶體區的一部分, 對於固定記憶體在linux內核中有下麵描述

x86 arm arm64
arch/x86/include/asm/fixmap.h?v=4.7, line 67 arch/arm/include/asm/fixmap.h?v=4.7, line 11 arch/arm64/include/asm/fixmap.h?v=4.7, line 36
/*
 * Here we define all the compile-time 'special' virtual
 * addresses. The point is to have a constant address at
 * compile time, but to set the physical address only
 * in the boot process.
 *
 * These 'compile-time allocated' memory buffers are
 * page-sized. Use set_fixmap(idx,phys) to associate
 * physical memory with fixmap indices.
 *
 */
enum fixed_addresses {
    FIX_HOLE,

    /*
     * Reserve a virtual window for the FDT that is 2 MB larger than the
     * maximum supported size, and put it at the top of the fixmap region.
     * The additional space ensures that any FDT that does not exceed
     * MAX_FDT_SIZE can be mapped regardless of whether it crosses any
     * 2 MB alignment boundaries.
     *
     * Keep this at the top so it remains 2 MB aligned.
     */
#define FIX_FDT_SIZE        (MAX_FDT_SIZE + SZ_2M)
    FIX_FDT_END,
    FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,

    FIX_EARLYCON_MEM_BASE,
    FIX_TEXT_POKE0,
    __end_of_permanent_fixed_addresses,

    /*
     * Temporary boot-time mappings, used by early_ioremap(),
     * before ioremap() is functional.
     */
#define NR_FIX_BTMAPS       (SZ_256K / PAGE_SIZE)
#define FIX_BTMAPS_SLOTS    7
#define TOTAL_FIX_BTMAPS    (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)

    FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
    FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,

    /*
     * Used for kernel page table creation, so unmapped memory may be used
     * for tables.
     */
    FIX_PTE,
    FIX_PMD,
    FIX_PUD,
    FIX_PGD,

    __end_of_fixed_addresses
};

1.2 固定映射

ioremap的作用是將IOBIOS以及物理地址空間映射到在896M至1G的128M的地址空間內, 使得kernel能夠訪問該空間併進行相應的讀寫操作。

start_kernel()->setup_arch()->early_ioremap_init()

然後arm和arm64上early_ioremap_init又是early_ioremap_setup的前端

函數 x86 arm arm64
early_ioremap_init arch/x86/mm/ioremap.c?v=4.7, line 445 arch/arm/mm/ioremap.c?v=4.7, line 489 arch/arm64/mm/ioremap.c?v=4.7, line 110
early_ioremap_setup mm/early_ioremap.c?v=4.7, line 67 體繫結構無關 體繫結構無關
/*
 * Must be called after early_fixmap_init
 */
void __init early_ioremap_init(void)
{
    early_ioremap_setup();
}

但是arm和arm64下的setup_arch函數則會先調用early_fixmap_init函數來填充fixmap. 參見arch/arm/kernel/setup.c?v=4.7, line 1058arch/arm64/kernel/setup.c?v=4.7, line 229.

void __init setup_arch(char **cmdline_p)
{
    early_fixmap_init();
    early_ioremap_init();
}

early_fixmap_init函數的定義在

arm arm64
arch/arm/mm/mmu.c?v=4.7, line 385 arch/arm64/mm/mmu.c?v=4.7, line 676

其中arm架構的定義如下所示, 在arch/arm/mm/mmu.c?v=4.7, line 385

void __init early_fixmap_init(void)
{
    pmd_t *pmd;

    /*
     * The early fixmap range spans multiple pmds, for which
     * we are not prepared:
     */
    BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
             != FIXADDR_TOP >> PMD_SHIFT);

    /*得到固定映射區的pmd
    ,此pmd為虛擬地址轉換為物理地址的pmd*/
    pmd = fixmap_pmd(FIXADDR_TOP);
     /*將bm_pte頁表設置為固定映射區開始地址的pmd的第一個頁表;*/
    pmd_populate_kernel(&init_mm, pmd, bm_pte);

    pte_offset_fixmap = pte_offset_early_fixmap;
}

1.3 ioremap函數

對於ioremap的使用需要通過early_memremapearly_iounmap進行.

由於對應於ioremap的記憶體空間是有限的, 所以對於ioremap空間的使用遵照使用結束馬上釋放的原則. 這就是說early_memremap和early_iounmap必須配對使用並且訪問結束必須馬上執行unmap

2 臨時內核映射

剛纔描述的kmap函數不能用於中斷處理程式, 因為它可能進入睡眠狀態. 如果pkmap數組中沒有空閑位置, 該函數會進入睡眠狀態, 直至情形有所改善.

因此內核提供了一個備選的映射函數, 其執行是原子的, 邏輯上稱為kmap_atomic. 該函數的一個主要優點是它比普通的kmap快速. 但它不能用於可能進入睡眠的代碼. 因此, 它對於很快就需要一個臨時頁的簡短代碼,是非常理想的.

kmap_atomic的定義在IA-32, PPC, Sparc32上是特定於體繫結構的, 但這3種實現只有非常細微的差別. 其原型是相同的.

2.1 kmap_atomic函數

//  http://lxr.free-electrons.com/source/arch/arm/mm/highmem.c?v=4.7#L55
void *kmap_atomic(struct page *page)

page是一個指向高端記憶體頁的管理結構的指針, 而早期的內核中, 增加了一個類型為enum km_typetype參數, 用於指定所需的映射類型

//  http://lxr.free-electrons.com/source/arch/arm/mm/highmem.c?v=2.6.32#L39
void *kmap_atomic(struct page *page, enum km_type type)

而在新的內核中, 刪除了這個標識, 但是保留了km_type的最大值KM_TYPE_NR

void *kmap_atomic(struct page *page)
{
    unsigned int idx;
    unsigned long vaddr;
    void *kmap;
    int type;

    preempt_disable();
    pagefault_disable();
    if (!PageHighMem(page))
        return page_address(page);

#ifdef CONFIG_DEBUG_HIGHMEM
    /*
     * There is no cache coherency issue when non VIVT, so force the
     * dedicated kmap usage for better debugging purposes in that case.
     */
    if (!cache_is_vivt())
        kmap = NULL;
    else
#endif
        kmap = kmap_high_get(page);
    if (kmap)
        return kmap;

    type = kmap_atomic_idx_push();

    idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
    vaddr = __fix_to_virt(idx);
#ifdef CONFIG_DEBUG_HIGHMEM
    /*
     * With debugging enabled, kunmap_atomic forces that entry to 0.
     * Make sure it was indeed properly unmapped.
     */
    BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
#endif
    /*
     * When debugging is off, kunmap_atomic leaves the previous mapping
     * in place, so the contained TLB flush ensures the TLB is updated
     * with the new mapping.
     */
    set_fixmap_pte(idx, mk_pte(page, kmap_prot));

    return (void *)vaddr;
}
EXPORT_SYMBOL(kmap_atomic);

這個函數不會被阻塞, 因此可以用在中斷上下文和起亞不能重新調度的地方. 它也禁止內核搶占, 這是有必要的, 因此映射對每個處理器都是唯一的(調度可能對哪個處理器執行哪個進程做變動).

2.2 kunmap_atomic函數

可以通過函數kunmap_atomic取消映射

/*
 * Prevent people trying to call kunmap_atomic() as if it were kunmap()
 * kunmap_atomic() should get the return value of kmap_atomic, not the page.
 */
#define kunmap_atomic(addr)                     \
do {                                \
    BUILD_BUG_ON(__same_type((addr), struct page *));       \
    __kunmap_atomic(addr);                  \
} while (0)

這個函數也不會阻塞. 在很多體繫結構中, 除非激活了內核搶占, 否則kunmap_atomic根本無事可做, 因為只有在下一個臨時映射到來前上一個臨時映射才有效. 因此, 內核完全可以”忘掉”kmap_atomic映射, kunmap_atomic也無需做什麼實際的事情. 下一個原子映射將自動覆蓋前一個映射.


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

-Advertisement-
Play Games
更多相關文章
  • [TOC] 1. 為什麼要爬蟲? “大數據時代”,數據獲取的方式: 大型企業公司有海量用戶,需要收集數據來提升產品體驗 【百度指數(搜索),阿裡指數(網購),騰訊數據(社交)】 數據管理咨詢公司: 通過數據團隊專門提供大量數據,通過市場調研,問卷調查等 政府/機構提供的公開數據 中華人民共和國統計局 ...
  • 列舉了task-based和value-based兩種拋異常情形的catch方法 ...
  • Visual Studio確實是相當好用,各種簡化操作什麼的簡直不要太舒服。但其容量太大,有時不是很方便,所以今天簡單介紹一下另一個工具--Visual Studio Code. 雖然相比於老大哥Visual Studio,VS Code有很多功能不完善,但它也更靈活輕便。並且VS Code還在不斷 ...
  • 1.閑聊 編碼一兩年, 我走過了欄位, 我跑過了類, 卻翻不過方法。(不能靈活使用方法吧) (寫這篇博客全程聽將夜中《永夜》歌曲寫完的,一氣呵成,安利一下) 2.敘事 我們在編碼中,經常搗鼓來搗鼓去的無非就是 “ 欄位,方法 ,類這三種。像欄位,類的使用(引用)很簡單,但是,方法的使用(引用,傳遞) ...
  • 策略模式:它定義了演算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓演算法的變化,不會影響到使用演算法的客戶。 今天來通過一個案例,來講一下商場的促銷案例。一般商場會有那些活動呢?總結了下,一般會有這3種促銷活動:1、正常收費;2、打折;3、滿多少返多少 面向對象的編程,並不是類越多越好,類的劃分 ...
  • 通過多態製作一個簡單的計算器 Operation類: 1 public class Operation 2 { 3 private double _numberA = 0; 4 private double _numberB = 0; 5 public double NumberA 6 { 7 ge ...
  • 很久沒用過EF了,最近換了公司,用的是EF框架,的確已經忘記了EF很多東西,雖說EF這東西性能不太好,但是可以滿足我們的快速開發,在新的項目中我遇到了操作中間表的問題,我記得大學的時候用過,但是年代久矣,那時候又沒有寫博客的習慣,現在就寫下來,以防又忘記了。 言歸正傳: EF中間表是隱藏起來的,在E ...
  • Intro 最近編譯類庫項目的時候發現總是有個 licenseUrl 的警告,警告信息如下: 本文針對的是使用新版項目文件打包的方式, .nuspec 官方文檔詳細,在此不多說。 新版的官方文檔里基本沒有提及,不過 Github 有個 "samples 項目" ,可以參考。 新版項目文件的 nuge ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...