Linux內存管理6---夥伴算法與slab

1.前言

本文所述關於內存管理的系列文章主要是對陳莉君老師所講述的內存管理知識講座的整理。前端

本講座主要分三個主題展開對內存管理進行講解:內存管理的硬件基礎、虛擬地址空間的管理、物理地址空間的管理.node

本文將主要以X86架構爲例來介紹夥伴算法和slab分配算法

2.夥伴算法概述

  • 塊鏈表

Linux的夥伴算法將全部的空閒頁面分紅MAX_ORDER+1(MAX_ORDER默認大小爲11)個塊鏈表數組

每一個鏈表中的一個節點指向一個含有2的冪次個頁面的塊,即頁塊或簡稱塊緩存

圖 夥伴算法結構實例圖數據結構

 0:每一個頁塊的大小爲1個頁架構

1:每一個頁塊的大小爲2個頁函數

。。。性能

MAX_ORDER:每一個頁塊的大小爲2的MAX_ORDER次方個頁3d

  • 夥伴

大小相同、物理地址連續的兩個頁塊稱爲夥伴

  • 夥伴算法工做原理

首先在大小知足要求的塊鏈表中查找是否有空閒塊,如有則直接分配,不然在更大的塊的塊鏈表中查找;

逆過程是塊的釋放,此時會把知足夥伴關係的塊合併,組成一個更大的塊,並插入到相應的塊鏈表中

3.與夥伴算法有關的數據結構

每一個頁框對應一個struct page實例

每一個內存區關聯一個struct zone區域,該結構中用free_area數組對空閒頁框進行管理

 

4.物理內存管理機制

  • 夥伴算法

負責大塊連續物理內存的分配和釋放,以頁框爲基本單位,避免外部碎片

  • slab緩存

負責小塊物理內存的分配,而且它也做爲一個緩存,主要針對內核中常常分配並釋放的對象

  • per-CPU頁框緩存

內核常常請求和釋放單個頁框,該緩存包含預先分配的頁框,用於知足本地CPU發出的單一頁框請求

5.夥伴算法分配原理

  • 夥伴算法的分配原理

若是分配階爲i的頁框塊,那麼先從第i條頁框塊鏈表中查找是否存在這麼大小的空閒塊。若是有則分配,不然在第i+1條鏈表中繼續查找,直到找到爲止

  • 夥伴算法分配舉例

若是申請大小爲8個(分配階爲3)頁的頁塊,但卻在頁塊大小爲32(分配階爲5)的鏈表中找到空閒塊,則先將這32個頁面對半等分,前一半做爲分配使用,另外一半做爲新元素插入下級大小爲16(分配階爲4)的鏈表中;

繼續將前一半大小爲16的頁塊等分,一半分配,另外一半插入大小爲8(分配階爲3)的鏈表中

6. 頁框分配的實現

5節描述的夥伴算法經過__rmqueue()主要調用以下兩個函數:

  • __rmqueue_smallest()

在指定的內存分配區上,從說請求分配階order對應的鏈表開始查找所需大小的空閒塊,若是不成功者從高一階的鏈表上繼續查找

  • expand()

若是所獲得的內存塊大於說請求的內存塊,則按照夥伴算法的分配原理將大的頁框塊分裂爲小的頁框塊

 

7.物理內存分配器

基於夥伴算法、每CPU高速緩存和slab高速緩存造成兩種內存分配器

  • 分區頁框分配器(zoned page frame allocator)

處理對連續頁框的內存分配請求。分區頁框分配器分爲兩大部分:前端的管理區分配器和夥伴系統

管理區分配器負責搜索一個能知足請求頁框大小的管理區;

在每一個管理區中,具體的頁框分配工做由夥伴系統負責,爲了達到更好的性能,單個頁框的申請直接由每cpu頁框高速緩存完成

圖 分區頁框分配器示例圖

  • slab分配器

將各類分配對象分區放進高速緩存,即每一個高速緩存都對同類型分配對象的一種「儲備」

 8. 頁框分配函數的關係圖

圖 頁框分配函數的關係

  • 內核有6個稍有差異的函數或宏來請求物理頁框,他們將核心的分配函數__alloc_pages_nodemask封裝知足不一樣的分配需求
  • 綠色函數返回線性地址,藍色函數返回頁塊的首頁框描述符的地址
  • __alloc_pages_nodemask是對分區頁框分配器的具體體現 

9. malloc的最終具體 

進程調用malloc()->

得到一塊虛擬內存->

內存訪問,若是還未分配物理內存->

發生缺頁異常->

內核調用__alloc_pages爲進程分配物理頁框,並將物理內存和虛擬內存的映射關係寫入頁表  

相關文章
相關標籤/搜索