2009年10月7日 星期三

DDK 記憶體配置及Linked-list處理

1.
分配Kernal記憶體
PVOID ExAllocatePool(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes);
PVOID ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag);
PVOID ExAllocatePoolWithQuota(IN POOL_TYPE, IN SIZE_T);
PVOID ExAllocatePoolWithQuataTag(IN POOL_TYPE, IN SIZE_T, IN UNLONG);
釋放Kernal記憶體
VOID ExFreePool(IN PVOID P);
NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, ULONG tag);

2.
Kernal使用link-list:
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY* Flink;
struct _LIST_ENTRY* Blink;
} LIST_ENTRY, *PLIST_ENTRY;

判斷 linked-list是否為空
IsListEmpty(PLIST_ENTRY);

插入element至 linked-list
InsertHeadList(PLIST_ENTRY head, PLIST_ENTRY entry);
InsertTailList(PLIST_ENTRY tail, PLIST_ENTRY entry);

從linked-list刪除element
RemoveHeadList(PLIST_ENTRY)
RemoveTailList(PLIST_ENTRY)

將element轉換成自訂資料結構
CONTAINING_RECORD(address, type, field) ;
address:自訂資料結構的位址
type:自訂的資料結構
filed:自訂資料結構中的pEntry

範例:
typedef struct _MYDATASTRUCT
{
ULONG number;
LIST_ENTRY ListEntry;
} MYDATASTRUCT, *PMYDATASTRUCT;

#pragma INITCODE
VOID LinkListTest()
{
LIST_ENTRY linkListHead;
//初始化鏈表
InitializeListHead(&linkListHead);

MYDATASTRUCT *pData;
ULONG i = 0;
//在鏈表中插入10個元素
KdPrint(("Begin insert to link list"));
for (i=0 ; i<5 ; i++)
{
pData = (MYDATASTRUCT *)ExAllocatePool(PagedPool,sizeof(MYDATASTRUCT));
pData->number = i;
InsertTailList(&linkListHead,&pData->ListEntry);
}

KdPrint(("Begin remove from link list\n"));
while(!IsListEmpty(&linkListHead))
{
PLIST_ENTRY pEntry = RemoveTailList(&linkListHead);
pData = CONTAINING_RECORD(pEntry,
MYDATASTRUCT,
ListEntry);
KdPrint(("%d\n",pData->number));
ExFreePool(pData);
}
}

3.
Lookaside結構:
避免頻繁配置及釋放記憶體,產生記憶體破碎的情況
使用前先要初始化,非分頁及分頁兩種方式
ExInitializeNPagedLookasideList (
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth
);

ExInitializePagedLookasideList (
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth
);

配置記憶體
PVOID ExAllocateFromNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST);
PVOIDExAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST);
釋放記憶體
VOID ExFreeToNPagedLookasideList(IN PNPAGED_LOOKASIDE, IN PVOID);
VOID ExFreeToPagedLookasideList(IN PPAGED_LOOKASIDE, IN PVOID);
使用完需要刪除Lookaside物件
VOID ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST);
VOID ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST);

範例:
typedef struct _MYDATASTRUCT
{
CHAR buffer[64];
} MYDATASTRUCT, *PMYDATASTRUCT;

#pragma INITCODE
VOID LookasideTest()
{
PAGED_LOOKASIDE_LIST pageList;
ExInitializePagedLookasideList(&pageList,NULL,NULL,0,sizeof(MYDATASTRUCT),'1234',0);

#define ARRAY_NUMBER 50
PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];
for (int i=0;i {
MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);
KdPrint(("Alloc MyObjectArray[%d]\n",i));
}

//模擬頻繁回收記憶體
for (i=0;i {
KdPrint(("Free MyObjectArray[%d]\n",i));
ExFreeToPagedLookasideList(&pageList,MyObjectArray[i]);

MyObjectArray[i] = NULL;

}

ExDeletePagedLookasideList(&pageList);
//刪除Lookaside物件
}

沒有留言 :