linux核心記憶體分配(一 基本概念)

2022-05-09 21:26:44 字數 2208 閱讀 3870

記憶體分配是linux比較複雜也是比較重要的部分,這個和ssd驅動很類似:實體地址和虛擬位址的對映關係。下面總結下最近看到的有關記憶體分配的內容和自己的理解;

上圖來自《深入linux裝置驅動程式核心機制》

簡單的說明下,uma(一致記憶體訪問 uniform memory access)可以很好的看到所有cpu訪問記憶體的距離都是一樣的(其實就是通過匯流排到記憶體的速度和距離都是一樣的)所以就叫一致記憶體訪問;

很顯然右邊的numa就是非一致記憶體訪問,記憶體節點0是cpu0的本地記憶體(雖然其他cpu也可以訪問,但是沒有cpu0的速度高),所以這樣各個cpu訪問記憶體節點都會首先選擇本地記憶體節點,然後再考慮其他記憶體節點;

上圖來自《深入linux裝置驅動程式核心機制》

首先大概的可以看出左邊的mem_map陣列中存放的是page結構體元素,中間的是實際的物理記憶體,右邊的是虛擬的位址範圍;

他們之間的關係大概是這樣的,mem_map陣列中的元素和物理記憶體頁聯絡,page指標指向中間的物理記憶體中的某個物理頁,這個關係是為了系統方便管理記憶體;

而物理記憶體頁和右邊的虛擬位址範圍對映,這個是為了操作物理記憶體,一般右邊的虛擬位址由cpu使用(軟體上使用的也是虛擬位址,不過該位址最終還是cpu使用)。cpu和mmu之間使用的都是虛擬位址,出了mmu後就轉換為實際的物理記憶體位址,一般有兩個地方使用:1、匯流排上;2、物理記憶體(可以理解為記憶體條上);

這裡模擬下ssd驅動的原理:ftl陣列中存放的是pba(lun、block、page、offset),而陣列下標為lba,pba是ssd上的實際實體地址,lba則是上層軟體使用的邏輯位址;他們通過ftl陣列來對映,這樣就可以通過修改陣列中的pba來實現ssd像硬碟那樣覆蓋寫等硬碟的特有效能;

回到記憶體分配上,從上面的圖中應該可以看出物理記憶體分為三大區域:zone_dma、zone_normal、zone_highmem;mem_map陣列和物理記憶體頁全部一一對映,也會形成三大區域;而在系統初始化期間,會把物理記憶體區域中zone_dma和zone_normal分別和右邊的虛擬位址「物理頁面直接對映區」(這個虛擬位址區域名稱有點怪,其實就是核心位址的0~896m位址範圍)建立線性對映,這樣就會建立相應的頁目錄和頁表;如果對右邊這個虛擬位址範圍分配有疑問的可以看看:不過這些都是在32位的系統中的,在64位系統中可以說完全不一樣,不過有這個概念會好點;

這時候,如果在核心記憶體zone_dma和zone_normal區域分配,則可以直接返回虛擬位址(0~896m)這個虛擬位址的界限不是固定的;如果需要在物理記憶體zone_highmem分配時,則要複雜些了;簡單的步驟為:1、在物理記憶體zone_highmem中查詢乙個空閒頁;2、在右邊的虛擬位址中的動態對映區或固定對映區分配乙個虛擬位址;3、建立頁目錄和頁表,使物理頁和虛擬位址對映起來;

首先是:alloc_pages(gfp_mask, order)巨集,(是不是很奇怪沒有先寫kmalloc、vmalloc,那是因為他們倆比較複雜,也比較重要,當然最主要的是他們不是分配物理頁。後面要用很大的篇幅來分析他們倆);引數 gfp_mask是乙個掩碼引數,用來控制分配行為(哪個區域分配、是否阻塞分配等);order是表示分配2的order次方個物理頁面;

alloc_pages(gfp_mask, order); 呼叫 alloc_pages_node(); 呼叫 __alloc_pages();說到底最後工作的還是__alloc_pages(),alloc_pages()和__alloc_pages()都可以分配來自zone_highmem區域的物理頁,主要看gfp_mask指定的分配區域; 注意alloc_pages()是巨集不是函式;

__get_free_pages(gfp_mask, order);這個分配函式首先是判斷gfp_mask,如果指定為zone_highmem分配區域,則失敗退出;否則,就呼叫alloc_pages()函式;由此看出__get_free_pages()函式只能分配zone_dma和zone_normal區域的物理頁,也就是說不需要修改頁表;

簡單的分配物理頁介面函式就這兩個,其他的都是些變種,根據gfp_mask,和order來實現的變種函式;

注意:這是分配多個的連續的物理頁的函式介面,kmalloc、vmalloc函式分配的不一定是整個頁大小的記憶體;

如果講解的不正確,歡迎指正,謝謝!!

linux核心記憶體分配

核心中的記憶體分配通常通過kmalloc kfree來進行,但是也有其它的方式來獲取記憶體,所有這些方式共同提供了核心中分配 釋放記憶體的介面。類似於標準c中的malloc free,kmalloc kfree是核心中的用於常規記憶體分配的介面。kmalloc kfree是工作在slab分配器的基礎...

Linux核心記憶體分配

函式有 kmalloc get free page get free pages get free page vmalloc kmem cache kmem cache alloclinux記憶體分為3中,dma 可以直接訪問 normal memory,high memory 一般記憶體中,前16...

核心記憶體的分配

當使用者態程序需要額外記憶體的時候,可以從核心所維護的空閒頁幀鍊錶中獲取頁,該鍊錶通常由頁替換演算法來更新,這些頁幀通常分散在物理記憶體當中,如果使用者只需要乙個位元組的記憶體,那麼會產生記憶體碎片,這是因為程序會得到整個頁幀 核心記憶體的分配通常是從空閒記憶體池中獲取的,而並不是從滿足普通使用者模...