LINUX 記憶體對映方式

2021-06-19 20:13:12 字數 3076 閱讀 5423

記憶體對映結構:

1、32位位址線定址4g的記憶體空間,其中0-3g為使用者程式所獨有,3g-4g為核心占有。

2、struct page:整個物理內存在初始化時,每個4kb頁面生成乙個對應的struct page結構,這個page結構就獨一無二的代表這個物理記憶體頁面,並存放在mem_map全域性陣列中。

3、段式對映:首先根據**段選擇子cs為索引,以gdt值為起始位址的段描述表中選擇出對應的段描述符,隨後根據段描述符的基址,本段長度,許可權資訊等進行校驗,校驗成功後。cs:offset中的32位偏移量直接與本段基址相累加,得出最終訪問位址。

0-3g與mem_map的對映方式:

因linux中採用的段式對映為flat模式,所以從邏輯位址到線性位址沒有變化。從段式出來進入頁式,每個使用者程序都獨自擁有乙個頁目錄表(pdt),執行時存放於cr3。 cr3(頁目錄) + 前10位 => 頁面表基址 + 中10位 => 頁表項 + 後12位 => 物理頁面位址

3g-4g與mem_map的對映方式:

分為三種型別:低端記憶體/普通記憶體/高階記憶體。

低端記憶體:3g-3g+16m 用於dma __pa線性對映

普通記憶體:3g+16m-3g+896m __pa線性對映 (若物理記憶體<896m,則分界點就在3g+實際記憶體)

高階記憶體:3g+896-4g 採用動態的分配方式

4、高階記憶體(假設3g+896為高階記憶體起址)

作用:訪問到1g以外的物理記憶體空間。

從記憶體分配函式的結構來看主要分為下面幾個部分:

a.夥伴演算法(最原始的面向頁的分配方式)

alloc_pages 介面:

struct page * alloc_page(unsigned int gfp_mask)--分配一頁物理記憶體並返回該頁物理記憶體的page結構指標。

struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)--分配 個連續的物理頁並返回分配的第乙個物理頁的page結構指標。

《釋放函式:__free_page(s)>

核心中定義:#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)

最終都是呼叫 __alloc_pages.

其中max_order 11,及最大分配到到頁面個數為2^10(即4m)。

void *page_address(struct page *page);

低端記憶體的對映方式:__va((unsigned long)(page - mem_map) << 12)

高階記憶體到對映方式:struct page_address_map分配乙個動態結構來管理高階記憶體。(核心是訪問不到vma的3g以下的虛擬位址的) 具體對映由kmap / kmap_atomic執行。

get_free_page介面:(alloc_pages介面兩步的替代函式)

unsigned long get_free_page(unsigned int gfp_mask)

unsigned long __get_free_page(unsigned int gfp_mask)

unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)

《釋放函式:free_page>

與alloc_page(s)系列最大的區別是無法申請高階記憶體,因為它返回到是乙個線性位址,而高階記憶體是需要額外對映才可以訪問的。

b.slab快取記憶體(反覆分配很多同一大小記憶體) 注:使用較少

kmem_cache_t* xx_cache;

建立: xx_cache = kmem_cache_create(「name」, sizeof(struct xx), slab_hwcache_align, null, null);

分配: kmem_cache_alloc(xx_cache, gfp_kernel);

釋放: kmem_cache_free(xx_cache, addr);

記憶體池mempool 不使用。

c.kmalloc(最常用的分配介面) 注:必須小於128kb

gfp_atomic 不休眠,用於中斷處理等情況

gfp_kernel 會休眠,一般狀況使用此標記

gfp_user 會休眠

__gfp_dma 分配dma記憶體

kmalloc/kfree

d.vmalloc/vfree

vmalloc採用高階記憶體預留的虛擬空間來收集記憶體碎片引起的不連續的物理記憶體頁,是用於非連續物理記憶體分配。

當kmalloc分配不到記憶體且無物理記憶體連續的需求時,可以使用。(優先從高階記憶體中查詢)

e.ioremap()/iounmap()

ioremap()的作用是把device暫存器和記憶體的實體地址區域對映到核心虛擬區域,返回值為核心的虛擬位址。使用的線性位址區間也在vmmlloc段

注:vmalloc()與 alloc_pages(_gfp_highmem)+kmap();前者不連續,後者只能對映乙個高階記憶體頁面

__get_free_pages與alloc_pages(normal)+page_address(); 兩者完全等同

核心位址通過 __va/__pa進行中低記憶體的直接對映

高階記憶體採用kmap/kmap_atomic的方式來對映

個人總結如下:

a.在<128kb的一般記憶體分配時,使用kmalloc

允許睡眠:gfp_kernel

不允許睡眠:gfp_atomic

b.在》128kb的記憶體分配時,使用get_free_pages,獲取成片頁面,直接返回虛擬位址(<4m)(或alloc_pages + page_address)

c.b失敗,

如果要求分配高階記憶體:alloc_pages(_gfp_highmem)+kmap(僅能對映乙個頁面)

如果不要求記憶體連續: 則使用vmalloc進行分配邏輯連續的大塊頁面.(不建議)/分配速度較慢,訪問速率較慢。

d.頻繁建立和銷毀很多較大資料結構,使用slab.

e.高階記憶體對映:

允許睡眠:kmap (永久對映)

不允許睡眠:kmap_atomic (臨時對映)會覆蓋以前到對映(不建議)

Linux 記憶體管理 高階記憶體的對映方式

cited from 解釋一 高階記憶體是指實體地址大於 896m 的記憶體。對於這樣的記憶體,無法在 核心直接對映空間 進行對映。為什麼?因為 核心直接對映空間 最多只能從 3g 到 4g,只能直接對映 1g 物理記憶體,對於大於 1g 的物理記憶體,無能為力。實際上,核心直接對映空間 也達不到 ...

Linux 記憶體管理 高階記憶體的對映方式

解釋一 核心在 fixaddr start 到 fixaddr top 之間保留了一些線性空間用於特殊需求。這個空間稱為 固定對映空間 在這個空間中,有一部分用於高階記憶體的臨時對映。這塊空間具有如下特點 1 每個 cpu 占用一塊空間 2 在每個 cpu 占用的那塊空間中,又分為多個小空間,每個小...

Linux 記憶體管理 高階記憶體的對映方式

分類 server開發2010 10 11 00 27 1146人閱讀 收藏舉報 linux struct linux核心 資料結構 table演算法 核心在 fixaddr start 到 fixaddr top 之間保留了一些線性空間用於特殊需求。這個空間稱為 固定對映空間 在這個空間中,有一部...