当前位置: 代码迷 >> 综合 >> UEFI EDKII 内存的分配和释放细节
  详细解决方案

UEFI EDKII 内存的分配和释放细节

热度:12   发布时间:2023-12-14 22:25:14.0

内存的分配和释放作为一种

该函数实现了以字节为单位的存储空间分配,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);