【原創】(四)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, Visio
1. 介紹
順著之前的分析,我們來到了bootmem_init()
函數了,本以為一篇文章能搞定,大概掃了一遍程式碼之後,我默默的把它拆成了兩部分。
bootmem_init()
函式程式碼如下:
void __init bootmem_init(void) { unsigned long min, max; min = PFN_UP(memblock_start_of_DRAM()); max = PFN_DOWN(memblock_end_of_DRAM()); early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT); max_pfn = max_low_pfn = max; arm64_numa_init(); /* * Sparsemem tries to allocate bootmem in memory_present(), so must be * done after the fixed reservations. */ arm64_memory_present(); sparse_init(); zone_sizes_init(min, max); memblock_dump_all(); }
這一部分,我們將研究一下Sparse Memory Model
。
在講Linux記憶體模型之前,需要補充兩個知識點:PFN
和NUMA
。
1.1 physical frame number(PFN)
前面我們講述過了虛擬地址到實體地址的對映過程,而系統中對記憶體的管理是以頁為單位的:
page
:線性地址被分成以固定長度為單位的組,稱為頁,比如典型的4K大小,頁內部連續的線性地址被對映到連續的實體地址中;
page frame
:記憶體被分成固定長度的儲存區域,稱為頁框,也叫物理頁。每一個頁框會包含一個頁,頁框的長度和一個頁的長度是一致的,在核心中使用struct page
來關聯物理頁。
如下圖,PFN從圖片中就能看出來了:
至於__page_to_pfn
這個實現取決於具體的實體記憶體模型,下文將進行介紹。
1.2 NUMA
UMA: Uniform Memory Access
,所有處理器對記憶體的訪問都是一致的:
從上圖中可以看出,當處理器和Core變多的時候,記憶體頻寬將成為瓶頸問題。
NUMA: Non Uniform Memory Access
,非一致性記憶體訪問:
從圖中可以看出,每個CPU訪問local memory,速度更快,延遲更小。當然,整體的記憶體構成一個記憶體池,CPU也能訪問remote memory,相對來說速度更慢,延遲更大。目前對NUMA
的瞭解僅限於此,在核心中會遇到相關的程式碼,大概知道屬於什麼範疇就可以了。
2. Linux記憶體模型
Linux提供了三種記憶體模型(include/asm-generic/memory_model.h
):
一般處理器架構支援一種或者多種記憶體模型,這個在編譯階段就已經確定,比如目前在ARM64中,使用的Sparse Memory Model
。
Flat Memory
實體記憶體地址連續,這個也是Linux最初使用的記憶體模型。當記憶體有空洞的時候也是可以使用這個模型,只是struct page *mem_map
陣列的大小跟實體地址正相關,記憶體有空洞會造成浪費。Discontiguous Memory
實體記憶體存在空洞,隨著Sparse Memory
的提出,這種記憶體模型也逐漸被棄用了。Sparse Memory
實體記憶體存在空洞,並且支援記憶體熱插拔,以section
為單位進行管理,這也是下文將分析的。
Linux三種記憶體模型下,struct page
到物理page frame
的對映方式也不一樣,具體可以檢視include/asm-generic/memory_model.h
檔案中的__pfn_to_page/__page_to_pfn
定義。
關於記憶體模型,可以參考Memory: the flat, the discontiguous, and the sparse
3. Sparse Memory
本節分析的是ARM64, UMA(linux4.14中不支援ARM NUMA)
下的Sparse Memory
模型。
3.1 mem_section
在Sparse Memory
模型中,section
是管理記憶體online/offline
的最小記憶體單元,在ARM64中,section
的大小為1G,而在Linux核心中,通過一個全域性的二維陣列struct mem_section **mem_section
來維護對映關係。
函式的呼叫過程如下所示,主要在arm64_memory_present
中來完成初始化及對映關係的建立:
函式呼叫結束之後的對映關係如下圖所示:
已知一個pfn
時,可以通過__pfn_to_section(pfn)
來最終找到對應的struct page
結構。
3.2 sparse_init
看看sparse_init
函式的呼叫關係圖:
在該函式中,首先分配了usermap,這個usermap與記憶體的回收機制相關,用4bit的bitmap來描述page block(一個pageblock大小通常為2的次冪,比如MAX_ORDER-1)
的遷移型別:
/* Bit indices that affect a whole block of pages */
enum pageblock_bits {
PB_migrate,
PB_migrate_end = PB_migrate + 3 - 1,
/* 3 bits required for migrate types */
PB_migrate_skip,/* If set the block is skipped by compaction */
/*
* Assume the bits will always align on a word. If this assumption
* changes then get/set pageblock needs updating.
*/
NR_PAGEBLOCK_BITS
};
sparse memory
模型會為每一個section都分配一個usermap
,最終的物理頁面的壓縮,遷移等操作,都跟這些位相關,如下圖所示:
sparse_init
函式中,另一部分的作用是遍歷所有present section
,然後將其對映到vmemmap區域空間。vmemmap
區域空間,在之前的文章中也提到過。執行完後,整體的效果如下圖所示:
關於Sparse Memory Model
就先分析這麼多,只有結合使用sparse memory
的具體模組時,理解才會更順暢。
一不小心就容易扣細節,而一旦陷入細節,核心就容易變成魔鬼,太難了。
相關推薦
【原創】(四)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記憶體管理之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記憶體管理 - 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記憶體管理 - 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程序排程-組排程及頻寬控制
# 背景 - `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 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程序排程-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,
【Java_SSM】(四)Eclipse中通過maven引入jar包
osc ati eight wid -- stat ack ips 技術 這篇博文我們介紹一下如何通過eclipse配置setting並引入jar包 (1)eclipse:Window--Preferences--Maven--User Setting 全部完成
Java併發程式設計(四)Java記憶體模型
前言 此前我們講到了執行緒、同步以及volatile關鍵字,對於Java的併發程式設計我們有必要了解下Java的記憶體模型,因為Java執行緒之間的通訊對於工程師來言是完全透明的,記憶體可見性問題很容易使工程師們覺得困惑,這篇文章我們來主要的講下Jav
啃碎併發(11):記憶體模型之重排序
0 前言 在很多情況下,訪問一個程式變數(物件例項欄位,類靜態欄位和陣列元素)可能會使用不同的順序執行,而不是程式語義所指定的順序執行。具體幾種情況,如下: 編譯器 能夠自由的以優化的名義去改變指令順序; 在特定的環境下,處理器 可能會次序顛倒的執行指令; 資料可能在 暫存器、處
【原創】OllyDBG 入門系列(四)-記憶體斷點
還是上次那個cm,不過這次的要求是寫出註冊機 那麼就要先研究註冊碼是怎麼來的,上次我們最開始找到的關鍵位置 00401306 |. /75 6B jnz short 00401373 00401308 |. |C1E8 1
【原創】(十一)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,