成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

說說Buddy算法的那些事

原創 精選
開發 前端
在本文中,我將重點介紹Buddy算法(又稱為伙伴算法),該算法是以頁為單位進行管理的。

作者 | 趙青窕

審校 | 孫淑娟

內核內存管理比較復雜,主要包含了Buddy算法,vmalloc管理,slab算法,kmapper及與初始化階段物理內存管理相關的兩個模塊memblock和bootmem。除了上述模塊外,還有內存遷移,水線檢測,kmemleak,內存信息統計,PCP等輔助內容。在本文中,我將重點介紹Buddy算法(又稱為伙伴算法),該算法是以頁為單位進行管理的。

Buddy算法介紹

目前,內核中的Buddy算法采用下圖的方式管理內存。我把Buddy算法分為如下圖所示的三部分,在區域一中,核心的數據結構是struct zone;在區域二中核心的數據結構是struct free_area free_area[MAX_ORDER];在區域三中,page鏈表是核心內容。接下來,我將詳細介紹這三個板塊,并通過分配函數來說明Buddy的工作細節。

圖 1 Buddy框架

1.區域

通常用zone代表不同的內存管理區,即把內存劃分成不同的組,每個組就是一個zone。

在內核中,每個zone通過結構體struct zone來表示,其結構體中主要成員如下:

struct zone {
unsigned long watermark[NR_WMARK];

unsigned long zone_start_pfn;
unsigned long managed_pages;
unsigned long spanned_pages;
unsigned long present_pages;
struct free_area free_area[MAX_ORDER];
const char *name;
struct pglist_data *zone_pgdat;
}
  • 標識內存水線的成員unsigned long watermark[NR_WMARK],其中NR_WMARK定義如下:
enum zone_watermarks {
WMARK_MIN,
WMARK_LOW,
WMARK_HIGH,
NR_WMARK
};

從上面定義可知,每個zone存在三個水線,若當前zone中空閑頁高于WMARK_HIGH,則當前zone區的空閑內存較多;若空閑頁低于WMARK_LOW,則交換守護進程開始將內存交換到磁盤上;若空閑頁低于WMARK_MIN,則內存回收系統還需要大量回收內存。在使用Buddy進行內存申請時,會進行水線判斷,從而進行相應的操作;

  • 伙伴系統管理相關的成員
unsigned long   zone_start_pfn;    
unsigned long managed_pages;
unsigned long spanned_pages;
unsigned long present_pages;
struct free_area free_area[MAX_ORDER]

前四個是相應zone區對應的頁號信息,free_area是伙伴算法中的關鍵成員,也是區域一和區域二銜接的關鍵成員,每個zone區會劃分為MAX_ORDER個組,數組free_area中的每個成員就代表一個組。

  • 成員const char *name指明了對應zone區的名稱,通常情況下為dma,Normal或highmem,其中highmem不會出現在64位的系統中;下面是典型的32位系統中的zone劃分方式:

ZONE_DMA(0~16M):DMA內存分配區;

ZONE_NORMAL(16MB~896MB):普通映射的內存區域;

ZONE_HIGHMEM(896MB~):高端內存區域,其中的頁不能永久映射到內核地址空間;內核一般不使用,如果要使用,通過kmap做動態映射;

  • 指向zone區對應node的指針成員struct pglist_data *zone_pgdat,node是內存管理中的一個重要成員。對于UMA架構,僅有一個node,所有的zone均屬于同一個node,但對于NUMA架構,會有多個不同的node,每個node又劃分為不同的zone,所有zone區也是通過struct pglist_data組織在一起的。

2.free_area和頁面鏈表

在內存管理和分配過程中,有一個重要參數order,當我們采用kmalloc申請大內存時,最后會調用函數__alloc_pages_nodemask來進行內存申請。該函數需要一個參數order,當order = 0時,表示要申請的內存大小是1(2的0次方)個頁面;當order = 1時,表示要申請的內存大小是2(2的1次方)個頁面。

次方在Buddy算法中,把內存按照2的冪次方(即2的order次方,order的范圍從0到MAX_ORDER)劃分成不同的組,每個組分別用對應的free_area[order]表示,例如free_area[0]對應的就是由內存塊大小為2的0次方的頁塊組成的組,free_area[1]對應的就是內存由塊大小為2的1次方的頁塊組成的組,而結構體結構區域正是通過成員free_area把圖1中的區域一和區域二串聯在一起。

結構體struct free_area定義如下(不同平臺或者不同內核會有差異,但核心思想相同):

struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};

從該結構可以看出,每一個free_area又根據MIGRATE_TYPES劃分為不同的組,每組分別通過鏈表free_list把同一類頁塊串聯在一起,這樣free_list就把圖1中的區域二和區域三串聯在一起了,從而間接的把區域一和區域三關聯在一起了。

結構體結構 page比較復雜,其中有一個成員結構list_head lru,通過該成員把圖1中區域三中的頁塊同區域二中對應的free_list鏈接在一起。

Buddy內存分配與釋放

在此,我將通過一個示例來簡要地展示Buddy內存分配的核心思想。當通過Buddy分配一個物理頁(即order = 0)時,會從對應zone區中free_area[0]管理的區域分配一個頁面(暫時先不考慮PCP的情況),并將該頁面從 free_area[0] 鏈表中移除;當free_area[0] 上沒有可用的物理頁時,Buddy會在free_area[1]上查找,若存在可用的物理頁,則將該頁塊從free_area[1] 的鏈表中移除,同時把該頁塊拆分成兩塊,其中一塊插入到free_area[0]中,另一塊傳遞給內存請求者;倘若free_area[1]上也沒有可用頁,則會繼續向上查找。

下圖2所示是沒有對應oder = 0的頁塊情況,因此把order = 1中的一個頁塊進行拆分,一半返回給order = 1的鏈表,一半返回給請求者。假如order = 1中沒有需要的頁塊,在內存分配過程中會繼續從order = 3中進行查找,直到找到頁塊或者遍歷完所有order。

圖 2 分配物理頁面示意圖

實際上,在整個內存分配過程中,會伴隨很多特殊情況處理。Buddy算法在進行內存分配時,會根據水線設置,來進行內存回收或者喚醒內核線程kswapd,或者是采用CPU的冷熱頁面隊列進行內存分配,或者是進行頁面移動等。假如已經嘗試頁面移動,kswapd已經喚出了一些頁面,同時也進行了內存回收,依然沒有可分配的內存,此時就會觸發out_of_memory。總之,這些特殊情況的處理方式均離不開圖1所示的Buddy框架。

下圖是我根據我本地的代碼整理的采用kmalloc申請大內存時的調用過程(使用kmalloc申請小內存時不通過Buddy),其中最關鍵的內存分配函數是prepare_alloc_pages,get_page_from_freelist,rmqueue 和__alloc_pages_slowpath。感興趣的朋友可以結合圖1所示的框架查看這幾個函數的具體實現。

當向系統釋放一個物理頁的時候,會通過struct page來推導出該page對應的zone區(比如該page屬于NORMAL區)和對應的page類型,緊接著將根據對應的order進行頁的合并(即圖1中區域三的部分進行合并),最后將合并后的塊插入到新的order中去,這個合并過程一直持續下去,直到不能合并或者已經合并到最大的order處。例如當釋放的物理頁得到其屬于NORMAL區的free_area[0],此時free_area[0]中存在頁面可以和釋放的頁面合并,從而把合并后的添加到free_area[1]中,這個合并操作會一直持續下去,直到合并完為止。這個過程實際上就是圖2的反過程。

總結

內存的管理比較復雜,本文主要介紹了Buddy的核心思想,但這僅僅是內存管理的冰山一角,卻是比較基礎且核心的內容,因此了解Buddy整體架構是非常有必要的。

作者介紹

趙青窕,51CTO社區編輯,從事多年驅動開發。研究興趣包含安全OS和網絡安全領域,發表過網絡相關專利。


責任編輯:華軒 來源: 51CTO
相關推薦

2009-07-29 10:36:04

北電收購

2015-07-06 11:35:07

預裝軟件

2015-05-28 10:07:20

溢算計算方式算法

2011-09-05 17:18:28

2021-01-25 10:05:27

ReactDOM前端

2011-04-14 14:23:06

軟件測試測試

2021-03-09 23:12:51

Python集合項目

2016-06-07 10:47:42

2011-09-19 15:40:35

2020-07-29 08:14:59

云計算云遷移IT

2014-06-06 16:08:17

初志科技

2019-11-20 10:00:56

開源侵權版權

2017-05-15 21:50:54

Linux引號

2024-02-04 17:03:30

2011-05-19 16:47:50

軟件測試

2012-05-01 08:06:49

手機

2012-05-31 09:53:38

IT風云15年

2010-07-27 11:29:43

Flex

2012-07-13 00:03:08

WEB前端開發WEB開發

2017-11-28 15:24:14

ETA配送構造
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91亚洲国产| 视频在线一区二区 | 国产日韩免费视频 | 久久99精品久久 | 亚洲国产一区二区三区在线观看 | 亚洲精品视频在线 | 五月天婷婷狠狠 | 91综合在线观看 | 国产伦精品一区二区三区照片91 | 日韩av一区二区在线观看 | 亚洲不卡在线观看 | 巨大荫蒂视频欧美另类大 | 国产一区二区三区在线免费 | www.免费看片.com | 艹逼网| 国产精品免费观看 | 国产精品99久久久久久久久久久久 | 欧美日韩国产传媒 | a级免费黄色片 | 亚洲成人一区 | 国产 欧美 日韩 一区 | 欧美视频在线看 | 精品欧美一区二区三区久久久 | 成人小视频在线观看 | 99成人 | 精品国产一区二区三区性色av | 最新中文字幕久久 | 欧美日韩国产一区二区三区 | 黑人精品欧美一区二区蜜桃 | 欧美成人精品 | 亚洲一区国产精品 | 国产日韩欧美综合 | 免费视频一区二区 | 国产精品揄拍一区二区 | 国产a级黄色录像 | 精品一区二区在线观看 | 亚洲综合视频 | 亚洲一区二区视频在线播放 | 免费人成激情视频在线观看冫 | 亚洲在线一区 | 91精品国产一区二区三区香蕉 |