Linux記憶體管理複習總結
首先來看一張圖:
這張圖就是Linux分配記憶體的大致流程。下面我來總結一下。
分頁
首先Linux是基於記憶體管理採用分頁機制,核心程式碼中它將所有段基址都設定為0,Linux採用這樣的方法直接避過了分段機制。僅僅用分段來控制使用者態和使用者態的訪問許可權。
核心記憶體分配
核心對於大塊記憶體的分配基於夥伴演算法,用來解決外部碎片的問題。夥伴演算法最低分配的單位是一頁。在實體記憶體的每個Zone中都有一個free_area[]陣列,分別儲存2的冪的頁面。夥伴演算法就是比如說申請8個頁面,然後首先去查詢free_area[3]有沒有可用的8個頁面,如果沒有就將上一級16個頁面一分為二,一部分分配出來,另一部分重新加入到free_area陣列對應8個頁面的位置。當記憶體釋放時,這兩個8個頁面又會重新合併。(這種互逆的操作將最大力度減小碎片的產生)。
夥伴演算法是基於一頁分配的,核心中對於遠小於一頁的位元組級別記憶體,比如task_struct結構體,使用夥伴演算法就會產生內部碎片。
為了解決內部碎片,Linux引入了slab機制。
slab機制
核心通常會對某些小物件頻繁進行分配,slab分配器通過對類似物件大小的快取提供這個功能。
slab分配器類似於一個全域性的物件池。可以快取不同大小的物件,最小一個快取行大小,最大則是128k。slab分配器有三層結構,分別是per-CPU的快取物件,CPU間共享的快取物件,每個NUMA節點共享的slab頁面。為了避免自旋鎖的競爭,核心分配快取物件優先從per-CPU陣列中獲取,並且獲取陣列最熱的物件。因為最熱的物件可能還在L1 cache中。如果per-CPU陣列中沒有物件分配,則回去CPU共享的shead陣列中查詢物件,如果還沒有,則會去針對NUMA節點的slab三個連結串列中查詢。這三個連結串列是slab滿連結串列,slab部分滿連結串列,slab空連結串列。分配物件從slab部分滿連結串列中查詢,如果部分滿連結串列中所有物件都分配出去了,則會將它加入slab滿連結串列之中。如果slab部分滿和空連結串列都沒有了,則會呼叫get_freepage()從夥伴系統分配2的冪的頁面。
slab機制實際上就是kmalloc的底層實現。
如果核心需要分配不連續的記憶體,那麼會呼叫vmalloc,vmalloc建立核心虛擬記憶體對物理儲存器的頁面對映,但由於vmalloc向夥伴系統要要記憶體不連續,所以相對kmalloc效率會低一些。vmalloc分配時使用__GFP_HIGHMEM標誌,優先從高階記憶體獲取物理頁。
vmalloc是對核心虛擬記憶體的對映,和程式記憶體分配類似,因使用缺頁中斷的機制,下面會說到。
程式的記憶體分配
建立程式fork(),動態記憶體malloc()都涉及到程式的記憶體分配。作業系統對於程式的記憶體分配,以mmap為例。malloc對於大於128k的記憶體使用mmap分配,mmap底層呼叫do_mmap(),由於是匿名對映,傳入file指標為NULL,然後會選擇呼叫當前程式的current->mm->get_unmapped_ared,在程式的虛擬地址空間分配一個VMA區域,並將該新的VMA加入到mm_struct管理的VMA連結串列和紅黑樹中。此時,核心並不為程式分配實際的物理頁面(頁表項標記不在記憶體)。當使用者程式第一次訪問這片記憶體時,虛擬地址經過MMU轉換,通過頁目錄查詢到相應頁表項,頁表項中標誌表明對應頁不再記憶體中。則觸發缺頁中斷。由於是匿名對映,核心在記憶體中找到一塊犧牲頁,將犧牲頁換出記憶體,將記憶體中該頁的位置清零,並修改相應頁表項。然後重啟引發缺頁中斷的指令,這時相應頁面已經在記憶體中了,程式就可以正常使用記憶體了。
參考:
相關文章
- linux記憶體管理學習總結Linux記憶體
- Linux 記憶體管理知識學習總結Linux記憶體
- 記憶體_管理總結記憶體
- JVM記憶體管理——總結篇JVM記憶體
- Java記憶體模型學習總結Java記憶體模型
- Linux 記憶體管理:記憶體對映Linux記憶體
- iphone 記憶體管理的一些總結iPhone記憶體
- linux記憶體管理Linux記憶體
- LINUX 記憶體管理Linux記憶體
- Linux 記憶體管理: KmallocLinux記憶體
- linux的記憶體管理Linux記憶體
- Linux記憶體管理:VmallocLinux記憶體
- Linux記憶體管理:MallocLinux記憶體
- Linux記憶體管理:DMALinux記憶體
- JVM記憶體模型總結JVM記憶體模型
- Linux下找出吃記憶體的方法總結Linux記憶體
- Spark學習——記憶體管理Spark記憶體
- 記憶體管理 記憶體管理概述記憶體
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- Linux共享記憶體的管理Linux記憶體
- Linux中的記憶體管理Linux記憶體
- linux記憶體管理機制Linux記憶體
- Linux 記憶體管理: Kmalloc(2)Linux記憶體
- linux記憶體管理(二)- vmallocLinux記憶體
- CUDA面記憶體用法總結記憶體
- oracle記憶體結構與管理Oracle記憶體
- 自動共享記憶體管理 自動記憶體管理 手工記憶體管理記憶體
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- 記憶體管理篇——實體記憶體的管理記憶體
- C++學習體會:記憶體管理C++記憶體
- [Virtualization]ESXi體系結構與記憶體管理(二)控制記憶體分配記憶體
- [Virtualization]ESXi體系結構與記憶體管理(三)控制記憶體分配記憶體
- 【記憶體管理】記憶體佈局記憶體
- Linux的記憶體分頁管理Linux記憶體
- Linux 的記憶體分頁管理Linux記憶體
- Linux 記憶體管理 pt.2Linux記憶體
- Linux 記憶體管理 pt.3Linux記憶體
- Linux-記憶體和磁碟管理Linux記憶體