UEFI EDKII 記憶體的分配和釋放細節
阿新 • • 發佈:2018-12-22
記憶體的分配和釋放作為一種
該函式實現了以位元組為單位的儲存空間分配,EDKII 中對這種非頁面的儲存空間使用瞭如下資料結構
來管理。
// // Each element is the sum of the 2 previous ones: this allows us to migrate // blocks between bins by splitting them up, while not wasting too much memory // as we would in a strict power-of-2 sequence // STATIC CONST UINT16 mPoolSizeTable[] = { 128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824 };
相同大小的pool 都被存放在同一個連結串列中
處理了請求分配大小超過FreeList 容量的情況,對於這種情況,直接呼叫page.c 檔案中的CoreAllocatePoolPagesI
函式去以頁面為單位分配。
將新新分配的頁面拆分成所需要的大小,並將這些可分配pool 加入到FreeList 陣列中去,拆分後剩餘的
空間“邊角料”也沒有浪費,而是被加入到更小單元的FreeList 陣列中去
// // Carve up remaining space into free pool blocks // Index--; while (Offset < MaxOffset) { ASSERT (Index < MAX_POOL_LIST); FSize = LIST_TO_SIZE(Index); while (Offset + FSize <= MaxOffset) { Free = (POOL_FREE *) &NewPage[Offset]; Free->Signature = POOL_FREE_SIGNATURE; Free->Index = (UINT32)Index; InsertHeadList (&Pool->FreeList[Index], &Free->Link); Offset += FSize; } Index -= 1; }
Index -= 1
先嚐試按最大的pool 來匹配,一直到嘗試能不能匹配上128位元組的記憶體單元。
// // Get the head & tail of the pool entry // Head = BASE_CR (Buffer, POOL_HEAD, Data); ASSERT(Head != NULL); if (Head->Signature != POOL_HEAD_SIGNATURE && Head->Signature != POOLPAGE_HEAD_SIGNATURE) { ASSERT (Head->Signature == POOL_HEAD_SIGNATURE || Head->Signature == POOLPAGE_HEAD_SIGNATURE); return EFI_INVALID_PARAMETER; }
該函式與AllocatePool 相對應,將已經分配的Pool 釋放以便可以重新利用這些儲存空間。函式
的一開始做了些Pool 結構的檢查工作,只有確實是通過AllocatePool 得到的空間才可以使用
FreePool來釋放。
同樣,對於大尺寸的Pool, 我們直接呼叫CoreFreePoolPage 來釋放相關頁面。對於通常的
Pool , 將這些空間重新加入到FreeList 中去。
//
// Put the pool entry onto the free pool list
//
Free = (POOL_FREE *) Head;
ASSERT(Free != NULL);
Free->Signature = POOL_FREE_SIGNATURE;
Free->Index = (UINT32)Index;
InsertHeadList (&Pool->FreeList[Index], &Free->Link);