分配内核函数
/************************************************************************ * 函数名称:ExAllocatePool * 功能描述:分配内核内存 * 参数列表: PoolType:是个枚举变量 NonPagedPool:分配非分页内存 PagedPool:分配分页内存 NonPagedPoolMustSucceed:指定分配非分页内存,必须成功 DontUseThisType:未指定 NonPagedPoolCacheAligned:指定要求分配非分页内存,而且必须内存对齐 PagedPoolCacheAligned:指定分配分页内存,而且必须内存对齐 NonPagedPoolCacheAlignedMustS:指定分配非分页内存,而且必须内存对齐,而且必须成功 NumberOfBytes:分配内存的大小,最好是4的倍数 Tag:系统在要求的内存外又额外地多分配了4个字节的标签 在调试的时候,可以找出是否有标有这个标签的内存没有被释放 * 返回 值: 返回分配的内存地址,一定是内核模式地址 如果为0,则代表分配失败 四个函数的功能类似 函数以WithQuota结尾的代表分配的时候按配额分配 函数以WithTag结尾的函数,和ExAllocatePool功能类似 *************************************************************************/ 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 PoolType, IN SIZE_T NumberOfBytes); PVOID ExAllocatePoolWithQuotaTag( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag);
释放内存
VOID ExFreePool(
IN PVOID p);
NTKERNELAPI VOID ExFreePoolWithTag(
IN PVOID p,
IN ULONG Tag);
Lookaside结构
Lookaside一般会在以下情况下使用:
1. 程序员每次申请固定大小的内存。
2. 申请和回收的操作十分频繁。
要使用Looaside对象,首先要初始化Lookaside对象,有以下两个函数可以使用:
//这两个函数分别是对非分页和分页Lookaside对象进行初始化 VOID ExInitializeNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth); VOID ExInitalizePagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth); //这两个函数分别是对非分页内存和分页内存的申请 PVOID ExAllocateFromNpagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside); PVOID ExAllocateFromPagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside); //这两个函数分别是对非分页内存和分页内存的回收 VOID ExFreeToNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry); VOID ExFreeToPagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry); //这两个函数分别是对非分页和分页Lookaside对象的删除 VOID ExDeleteNPagedLookasideList( IN PNPAGED_LOOKASIDE_LIST Lookaside); VOID ExDeletePagedLookasideList( IN PPAGED_LOOKASIDE_LIST Lookaside);
/************************************************************************ * 函数名称:LookasideTest * 功能描述:利用Lookaside对象频繁地申请和回收内存 * 参数列表: * 返回 值:VOID *************************************************************************/ #pragma INITCODE VOID LookasideTest() { //初始化Lookaside对象 PAGED_LOOKASIDE_LIST pageList; ExInitializePagedLookasideList( &pageList, NULL, NULL, 0, sizeof(MYDATASTRUCT), '1234', 0); #define ARRAY_NUMBER 50 PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER]; //模拟频繁申请内存 int i; for (i=0; i<ARRAY_NUMBER; i++) { MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList); } //模拟频繁回收内存 for(i=0; i<ARRAY_NUMBER; i++) { ExFreeToPagedLookasideList(&pageList, MyObjectArray[i]); MyObjectArray[i] = NULL; } //删除Lookaside对象 ExDeletePagedLookasideList(&pageList); }
内存间复制
/************************************************************************ * 函数名称:RtlCopyMemory * 功能描述:内存间复制(非重叠) * 参数列表: Destination:表示要复制内存的目的地址 Source:表示要复制内存的源地址 Length:表示要复制内存的长度,单位是字节 * 返回 值:VOID *************************************************************************/ VOID RtlCopyMemory( IN VOID UNALIGNED *Destination, IN CONST VOID UNALIGNED *Source, IN SIZE_T Length); /************************************************************************ * 函数名称:RtlMoveMemory * 功能描述:内存间复制(可重叠) * 参数列表: Destination:表示要复制内存的目的地址 Source:表示要复制内存的源地址 Length:表示要复制内存的长度,单位是字节 * 返回 值:VOID *************************************************************************/ VOID RtlMoveMemory( IN VOID UNALIGNED *Destination, IN CONST VOID UNALIGNED *Source, IN SIZE_T Length);
填充内存
/************************************************************************ * 函数名称:RtlFillMemory * 功能描述:内存填充 * 参数列表: Destination:目的地址 Length:长度 Fill:需要填充的字节 * 返回 值:VOID *************************************************************************/ VOID RtlFillMemory( IN VOID UNALIGNED *Destination, IN SIZE_T Length, IN UCHAR Fill); #define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length)) /************************************************************************ * 函数名称:RtlZeroMemory * 功能描述:对某段内存填零 * 参数列表: Destination:目的地址 Length:长度 * 返回 值:VOID *************************************************************************/ VOID RtlZeroMemory( IN VOID UNALIGNED *Destination, IN SIZE_T Length); #define RrlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
内存比较
/************************************************************************ * 函数名称:RtlZeroMemory * 功能描述:内存比较 * 参数列表: Source1:比较的第一个内存地址 Source2:比较的第二个内存地址 Length:比较的长度,单位为字节 * 返回 值:相等的字节数 不一致返回零 *************************************************************************/ ULONG RtlEqualMemory( CONST VOID *Source1, CONST VOID *Source2, SIZE_T Length); #define RtlEqualMemory(Destination, Source, Length) (!memcmp((Destination), (Source), (Length)))
检验内存间赋值、填充内存、内存比较
/************************************************************************ * 函数名称:RtlTest * 功能描述:检验内存间赋值、填充内存、内存比较 * 参数列表: * 返回 值:VOID *************************************************************************/ #define BUFFER_SIZE 1024 #pragma INITCODE VOID RtlTest() { PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE); //用零填充内存 RtlZeroMemory(pBuffer, BUFFER_SIZE); PUCHAR pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE); //用固定字节填充内存 RtlFillMemory(pBuffer2, BUFFER_SIZE, 0xAA); //内存复制 RtlCopyMemory(pBuffer, pBuffer2, BUFFER_SIZE); //判断内存是否一致 ULONG ulRet = RtlCompareMemory(pBuffer, pBuffer2, BUFFER_SIZE); if(ulRet == BUFFER_SIZE) { KdPrint(("The two blocks are same. \n")); } }
使用C++特性分配内存
//全局new操作符 void* _cdecl operator new(size_t size,POOL_TYPE PoolType=PagedPool) { KdPrint(("Global operator new \n")); KdPrint(("Allocate size :%d\n", size)); return ExAllocatePool(PoolType, size); } //全局delete操作符 void _cdecl operator delete(void* pointer) { KdPrint(("Global delete operator\n")); return ExFreePool(pointer); } class TestClass { public: //构造函数 TestClass() { KdPrint(("TestClass::TestClass()\n")); } //析构函数 ~TestClass() { KdPrint(("TestClass::~TestClass()\n")); } //类中的new操作符 void* operator new(size_t size,POOL_TYPE PoolType=PagedPool) { KdPrint(("TestClass::new\n")); KdPrint(("Allocate size :%d\n", size)); return ExAllocatePool(PoolType, size); } //类中的delete操作符 void operator delete(void* pointer) { KdPrint(("TestClass::delete\n")); return ExFreePool(pointer); } private: char buffer[1024]; }; void TestNewOperator() { //测试new操作 TestClass* pTestClass = new TestClass; //测试delete操作符 delete pTestClass; pTestClass = new(NonPagedPool) TestClass; delete pTestClass; char* pBuffer = new(PagedPool) char[100]; delete []pBuffer; pBuffer = new(NonPagedPool) char[100]; delete []pBuffer; }