動態記憶體管理
切分與合併區塊(splitting and coalescing)
配置器不斷重塑它那池閒置記憶體,以符合收到的請求。兩種操作完成了大部分的重塑。切分是把一塊大的閒置區塊切成給你的較小一塊、加上剩下的閒置一塊。合併(有時稱為融合)則相反:把兩塊相鄰的閒置區塊黏回成一塊更大的閒置區塊。兩者一起讓閒置池保持彈性,而不必一直回頭找核心。
切分,具體地說:假設手上最小的閒置區塊是 100 個位元組,而你要求 24 個。配置器不會把整塊給你而浪費 76 個位元組,它會切下一塊 24 位元組(外加其標頭)給你,把剩下的位元組變成一塊較小的閒置區塊,放回自由串列供未來請求使用。合併發生在釋放時,用來對抗切分可能造成的損害。當你釋放一塊區塊時,配置器檢查記憶體中與它實體相鄰的區塊是否也是閒置的;若某個鄰居是閒置的,就把它們合併成一塊更大的閒置區塊。沒有合併的話,一長串配置後釋放會把堆積剁成一堆細碎的閒置碎片——外部碎片——稍後一個大請求就會失敗,儘管閒置空間總量充足。把相鄰的空洞重新併回去,能恢復出大塊的連續區域。
癥結在於合併只能作用於實體相鄰的區塊,所以配置器需要知道每塊的大小及其鄰居。這就是為什麼區塊帶有標頭(有時還有頁尾)記錄它們的大小與閒置/使用狀態——好讓配置器能從一塊算出下一塊從哪裡開始、以及能否合併。切分與合併是真實配置器在滿足請求與避免記憶體碎片之間取得平衡的日常機制。
切分:一塊 100 位元組的閒置區塊,請求 24 -> [24 已用 | 76 閒置]。 釋放時合併:[16 閒置][16 剛釋放][16 閒置] -> 一塊 [48 閒置] 區塊。
切分剛好切出你需要的;合併把相鄰的閒置鄰居併起來以對抗碎片。
合併只能併實體相鄰的閒置區塊——中間夾著一塊已用區塊的兩塊閒置區塊無法接合,這也是為什麼外部碎片仍可能累積。
又稱
另見