现在的位置: 首页 > 综合 > 正文

ExAllocatePool函数

2013年12月17日 ⁄ 综合 ⁄ 共 2448字 ⁄ 字号 评论关闭

如同C里面的malloc一样,内核模式下的ExAllocatePool也是非常重要的.但是一说到ExAllocatePool函数就不得不提ExAllocatePoolWithTag函数.对比一下两个函数的调用方式:

 

     PVOID p = ExAllocatePool(Pool_Type, Size);

    PVOID p = ExAllocatePoolWithTag(Pool_Type, Size, Tag);

 

    在调用ExAllocatePoolWithTag的时候,系统会在要求的内存大小的基础上再额外多分配4个字节的标签.这个标签占用了开始的4个字节,位于返回指针所指向地址的前面.这样,当调试时这个标签可以帮助你识别有问题的内存块.

   在WDM.H(NTDDK.H)中声明了,内存分配函数无条件受预处理宏POOL_TAGGING控制(POOL_TAGGING被无条件的定义).因此,即便是调用的ExAllocatePool函数,实际执行的却是:ExAllocatePoolWithTag,其加入的标签为"mdW",指明是WDM的内存块.

   又或者你强行关闭POOL_TAGGING宏再去调用ExAllocatePool,实际执行的还是ExAllocatePoolWithTag,并带标签"enoN".

   因此,建议在分配内存时,直接调用ExAllocatePoolWithTag并加上一个自定义的标签.

================================================================================================================

内核模式中的基本堆分配函数是ExAllocatePool。
1.调用方式如下:
PVOID p = ExAllocatePool(type, nbytes);

2.参数
type参数是常量,如下表所示。
     POOL_TYPE            描述 
     NonPagedPool          从非分页内存池中分配内存 
     PagedPool                从分页内存池中分配内存 
     NonPagedPoolMustSucceed      从非分页内存池中分配内存,如果不能分配则产生bugcheck 
     NonPagedPoolCacheAligned        从非分页内存池中分配内存,并确保内存与CPU cache对齐 
     NonPagedPoolCacheAlignedMustS   与NonPagedPoolCacheAligned类似,但如果不能分配则产生bugcheck
     PagedPoolCacheAligned           从分页内存池中分配内存,并确保内存与CPU cache对齐
nbytes是要分配的字节数。
返回值是一个内核模式虚拟地址指针,指向已分配的内存块。如果内存不足,则返回一个NULL指针。

3.使用原则
调用ExAllocatePool时的最基本原则是被分配内存块是否可以交换出内存。
这取决于驱动程序的哪一部分需要访问这块内存。如果在大于或等于DISPATCH_LEVEL级上使用该内存块,那么必须从非分页池中分配内存。如果你总是在低于DISPATCH_LEVEL级上使用内存块,那么既可以从非分页池中分配内存也可以从分页池中分配内存。

4.对齐
你获得的内存块至少是按8字节边界对齐的。如果把某结构的实例放到分配的内存中,那么编译器赋予结构成员的4或8字节偏移在新内存中也将是4或8字节偏移。但在某些RISC平台上,结构成员可能以双字和四字对齐。出于性能上的考虑,希望内存块能适合处理器cache行的最少可能数,使用XxxCacheAligned类型代码可以达到这个要求。如果请求的内存多于一页,那么内存块将从页的边界开始。

5.内存释放
调用ExFreePool可以释放由ExAllocatePool分配的内存块:
ExFreePool((PVOID) p);
 
6.ExAllocatePoolWithTag函数
PVOID p = ExAllocatePoolWithTag(Pool_Type, Size, Tag);
在调用ExAllocatePoolWithTag的时候,系统会在要求的内存大小的基础上再额外多分配4个字节的标签.这个标签占用了开始的4个字节,位于返回指针所指向地址的前面。调试时,如果你查看分配的内存块会看到这个标签,它帮助你识别有问题的内存块。例如:
PVOID p = ExAllocatePoolWithTag(PagedPool, 42, 'KNUJ');  //使用了一个32位整数常量作为标签值
 
7.预处理宏POOL_TAGGING
WDM.H(NTDDK.H中也是)中无条件地定义了POOL_TAGGING,结果,无标签的函数实际上是宏,它真正执行的是有标签函数并加入标签‘ mdW’(指明为WDM的内存块)。
#ifdef POOL_TAGGING
 #ifdef ExAllocatePool
  #undef ExAllocatePool
 #endif
 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'frPD')
#endif
由于POOL_TAGGING宏的存在,当你在程序中调用ExAllocatePool时,最终被调用的将是ExAllocatePoolWithTag。如果你关闭了该宏,自己去调用ExAllocatePool,但ExAllocatePool内部仍旧调用ExAllocatePoolWithTag并带一个‘enoN’(即None)的标签。因此你无法避免产生内存标签。所以你应该明确地调用ExAllocatePoolWithTag并加上一个你认为有意义的标签。实际上,Microsoft强烈鼓励你这样做。

【上篇】
【下篇】

抱歉!评论已关闭.