STL 一級 二級空間配置器

2022-08-03 11:12:11 字數 2282 閱讀 4639

內碎片:需要3位元組,系統分配4位元組,剩下的1位元組就是內碎片

外碎片:由於不斷申請記憶體和歸還記憶體使得記憶體中剩下很多小片段的記憶體,無法被利用

作用:(1)提高**復用率,功能模組化。

(2)減少記憶體碎片問題。

(3)提高記憶體分配的效率。

(4)有記憶體不足時的應對措施。

(5)隱藏實際中對儲存空間的分配及釋放細節,確保所有被分配的儲存空間都最終獲得釋放。

(5)考慮多執行緒狀態。

考慮到小型區塊可能導致的記憶體碎片問題,設定了兩級空間配置器。分別為:一級空間配置器、二級空間配置器。當區塊大於128位元組,呼叫一級空間配置器;小於等於128位元組,為了降低額外開銷,用底層較複雜的二級空間配置器。

一級空間配置器

分為三個函式

allocate用於分配空間,如果申請失敗,用oom_alloc重新嘗試申請。

deallocate用於釋放空間。

reallocate用於根據需要自己調整已經存在的空間大小,如果申請調整失敗,用oom_realloc嘗試申請。

sgi二級空間配置器的原理是:當區塊小於128位元組,則以記憶體池(memory pool)管理,**時管理乙個使用者歸還的空間,類似於雜湊桶。每次配置一塊記憶體,並維護對應的自由鍊錶(free_list)。為了方便管理,sgi二級配置器會對齊到8個位元組。(例:需要30位元組的空間,自動調整到32位元組)。維護16個free_lists,各自管理大小分別為

8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128位元組。

記憶體池開始位置:start_free

記憶體池結束位置:end_free

所需空間的大小:n

記憶體池大小:heap_size=end_free-start_free.

一次二級空間配置器的示例

以申請12位元組的空間為例講解一下二級空間配置器處理空間申請的過程-------12位元組會被上調到8的整數倍,也就是16.

首先去對應自由鍊錶裡邊找(通過位元組數16對齊到計算出對應位置為1號自由鍊錶),看自由鍊錶對應位置有沒有空間,如果有,就採用頭刪的方式將自由鍊錶上掛接的第乙個空間結點分配給使用者使用,然後將剩下的空間繼續掛接起來空間申請就結束了,簡單又高效。但是如果0號自由鍊錶中沒有空間,就需要去記憶體池裡邊申請了,如果就向記憶體池申請一塊 16個位元組的空間,下一次申請16位元組空間的時候自由鍊錶中依然是沒有空間,又要到記憶體池裡邊申請,每次都這樣,很麻煩,所以,在向記憶體池裡申請空間的時候,不是一次只申請一塊16個位元組的空間,而是多申請幾塊16位元組的空間(比如20塊),方便下一次 16位元組空間的申請。

到記憶體池裡邊申請空間,又有三種情況,第一種情況:記憶體池裡邊空間還很足,16位元組大小的空間還可以分配出20塊,那麼,將其中1塊分配給使用者使用,然後將剩下的19塊掛接到自由鍊錶中,下一次申請16位元組的空間就可以直接在自由鍊錶中取了。第二種情況:記憶體池裡邊空間不是很足,不能一次性提供 20 個塊 16個位元組的空間,但是可以提供5塊 16位元組的空間(不一定是5 ,只要比20小,大於等於1就行),那麼,就將能提供的這5塊空間的其中一塊返回給使用者使用,剩下的4塊掛接到自由鍊錶中;第三種情況:記憶體池裡的空間已經很緊張了,假如只剩下8個位元組,連一塊16位元組的空間都提供不了了,那麼這個時候就需要朝系統去申請空間來填充記憶體池了,由於管理記憶體池的就是乙個_start  和 _end 指標,只能標記上一塊連續的空間,所以,之前記憶體池中還剩的8個位元組的空間就需要將它掛接到對應的自由鍊錶(也就是0號自由鍊錶)中,然後向系統申請一端空間放入到記憶體池中,並用_start  和 _end 指標將這段空間標記管理起來。這就回到了第一種情況。

向系統申請一大塊空間就一定能申請成功麼?不一定,如果系統裡邊的空間也已經不足了就會申請失敗,這個時候,就需要向自由鍊錶後邊管理的比16位元組大的空間裡邊去切割了,因為不確定那個自由煉表裡有空間,所以,需要遍歷管理自由鍊錶的陣列,在遍歷的時候有乙個小細節,目前我們申請的16位元組的空間對應的是1號自由鍊錶,按理說我們應該從2號自由鍊錶開始查詢,但是由於需要考慮多執行緒,(有可能在我們向記憶體池或系統申請空間的時候,另乙個執行緒已經歸還空間並掛接到了1號自由鍊錶中),所以,依然從1號自由鍊錶開始遍歷。當遍歷到某個自由鍊錶(假如是3號自由鍊錶中管理的有空間),那麼,就從3號自由鍊錶中取乙個空間結點下來(同樣是以頭刪的方式)放入到記憶體池中,然後再使用在記憶體中申請空間的方式申請空間就ok了

如果一直將後邊全部的自由鍊錶都遍歷完了,也沒有找到一塊空間。也就是說所有自由鍊錶、記憶體池、系統裡都不能提供空間,可以說是山窮水盡了。空間都去哪了?已經分配給使用者了,那麼,只能呼叫一級空間配置器,因為一直空間配置器在無法分配空間的時候會呼叫使用者設定的記憶體釋放函式,將自己已經不用的空間歸還給系統,這樣就有可能還能申請到空間,如果使用者沒有設定記憶體釋放函式的話,那麼申請空間的結果就只能是失敗(拋異常)了。

STL二級空間配置器

stl的二級空間配置器類似於memory pool,但是並不是memory pool,因為stl的二級空間配置器只維護了16個free list,而且只是小於128byte大小的小區塊,大於128byte會呼叫一級空間配置器malloc。16個鍊錶放在陣列中,每乙個陣列所鏈的鍊錶代表大小相等的小區塊...

STL 空間配置器二 第一級配置器

慮到小型區塊可能造成的記憶體破碎問題,sgi 為此設計了雙層級配置器。當配置區塊超過 128bytes 時,稱為足夠大,使用第一級配置器,直接使用 malloc 和 free 當配置區塊不大於 128bytes 時,為了降低額外負擔,直接使用第二級配置器,採用複雜的 memory pool 處理方式...

一級指標二級指標

例如 int p null int代表指標p指向的資料型別是int型,代表這是乙個指標變數,1 指標變數儲存的內容是指向的變數的位址 2 在使用sizeof判斷指標的位元組數時,在32位機器上為4個位元組,在64位機器上為了相容,仍然是四個位元組大小 3 小知識點,不同型別的指標除了指向的變數資料型...