如同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并加上一个自定义的标签.

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

ExAllocatePoolWithTag

功能描述:

ExAllocatePoolWithTag函数:根据指定存储区类型参数分配一段空间,并把该空间的首地址作为返回值发送给调用者。

参数说明:

PoolType
该参数用来指定想要申请的内存的类型(内核空间中的内存主要分成两类;分页内存区,和未分页内存区)。查询可选的内存区类型可以到MSDN查询POOL_TYPE结构。

您也可以修改该参数,将当前的值和标志POOL_RAISE_IF_ALLOCATION_FAILURE进行或运算(使用运算符:||)。标志POOL_RAISE_IF_ALLOCATION_FAILURE的作用是在申请空间的请求无法被实现的时候(空间不足?权限不足?)报出异常。但是我们不建议您过多使用这个标志位,因为它对程序的性能影响太大~

同样,您也可以把当前的PoolType和另一个标志POOL_COLD_ALLOCATION进行或运算(使用运算符:||)。这个标志的功能是提示系统从那些快要页面溢出(Paged-out)的页中分配空间(反正这个页面中数据基本坏了,直接分配给其他人用,是这意思吗?)。为了尽可能的减少常驻存储器池的数量,您还是少用这个标志。同时POOL_COLD_ALLOCATION 标志位只建议您在XP和之后的windows版本中使用(看来其中有不可告人的秘密)。

NumberOfBytes
通过该参数指定想要分配的内存的字节数。

Tag
为将要被分配的空间指定标志(就是给你得到的空间取个独一无二的名字)。进一步解释:赋给该参数的内容是一个字符串常量,最多可以包含四个字母,该字符串应该放到单引号当中(比如:‘tag1’‘tag2’)。另外,这个字符串常常是逆序的,如,‘1gaT’(所以大家会发现输入这个参数的串确实都是倒过来的。。。)。输入到这个参数中的每一个字符的ASCII值都必须在0-127之间。每次的申请空间的时候都最好应该使用一个独一无二的标识,这样可以帮助调试器和检查器辨认和分析。

返回值:
如果该函数发现目前系统的自由空间不足,就会返回NULL。否则,将返回指向被分配出来的空间的首地址。

附加说明:
这个函数用于普通的申请内存空间。
如果参数NumberOfBytes 的值大于等于PAGE_SIZE ,那么函数就会按照页对齐(以页为单位)分配空间。当分配小于等于一个页大小的空间时,函数会在一个单独的页中进行分配,也就是说该情况下分配的空间不会夸页。同时,分配少于一个页大小的空间时,分配是以字节为对齐单位,在32位系统中以8字节对齐,在64位系统中以16字节对齐。
要成功的用该函数申请空间,需要在申请非分页内存区的时候,参数NumberOfBytes 小于PAGE_SIZE,并且要给出想要申请的准确字节数。如果成功的申请到了大于一个页的空间,并且参数NumberOfBytes不是页大小的倍数,那么最后一页会含有不属于该函数调用者的空间。如果可能的话,内存分配管理器会占用这些空间。为了防止发生数据访问冲突,驱动程序只能操作已经显式申请过的存储空间。

系统将空间标识(第三个参数)和空间绑定起来。调试器,如WinDbg,可以显式这些和内存空间绑定在一起的标识符。Gflag(一个windows自带的调试工具),可以开启一个系统功能——请求为一个特定的标示符申请专有的空间。Poolmon,该工具包含在WDK中,可以通过给定的标示符追踪内存区域。

Tag参数的值有时候会被以逆序的方式存储或者显示。如一个调用函数传进来参数‘Fred’。而这个参数在其他地方或者被其他调试器显示出来时则是‘derF’。而在寄存器和某些工具中显示为‘0x64657246’

该函数申请到的空间在释放的时候可以使用ExFreePool或者ExFreePoolWithTag。

函数ExAllocatePoolWithTag的调用者的内核中断级必须小于等于DISPATCH_LEVEL。如果调用者在DISPATCH_LEVEL级上执行,必须使用NonPagedXxx给PoolType复制,如果调用者的工作中断级小于等于APC_LEVEL,那么它在类型参数上也可以使用POOL_TYPE。但是中断级和其他环境参数必须充分考虑分页类型的空间。

注意:不要把NumberOfBytes设置成0,这会造成空间浪费,因为系统会给每一次分配的空间加一个头,哪怕分配的空间大小是0,同时还会在函数的调用者代码中产生一些潜在的问题。
注意:被ExAllocatePoolWithTag分配出来的空间是没有经过初始化的。一个内核驱动如果打算申请一段空间,并且让应用层的程序可以访问这个空间,必须先对它进行清零的初始化。

内存分配函数 ExAllocatePool ExAllocatePoolWithTag相关推荐

  1. 替换libc中的内存分配函数

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 本文介绍如何替换glibc中的内存分配函数为自定义的内存分配函数的方法,可以方便调试内存分配,和查找内存管理错误而产生 ...

  2. 【C/C++】内存分配函数:malloc,calloc,realloc,_alloca

    [C/C++]内存分配函数:malloc,calloc,realloc,_alloca malloc: 原型:extern void *malloc(unsigned int num_bytes); ...

  3. 内存分配函数 malloc、realloc、calloc

    C 语言主要提供 malloc.realloc.calloc.alloca 与 aligned_alloc 等内存分配函数来实现对内存的分配功能. 1) malloc 函数原型如下: void * m ...

  4. linux内核函数kmalloc,Linux_Linux平台上几个常见内核内存分配函数,* kmallocPrototype:#incl - phpStudy...

    Linux平台上几个常见内核内存分配函数 * kmalloc Prototype: #include void *kmalloc(size_t size, int flags); Kmalloc分配一 ...

  5. Linux内核中常见内存分配函数

    1.      原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系统中,用到了四级页表,如图2-1所示.四级页表分 ...

  6. Linux内核中内存分配函数

    1.原理说明 Linux内核 中采 用了一种同时适用于32位和64位系统的内 存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系 统中,用到了四级页表,如图2-1所示.四级页表分别为 ...

  7. c语言字符指针分配内存,内存分配函数及使用注意事项,C语言内存分配函数完全攻略...

    C 语言主要提供 malloc.realloc.calloc.alloca 与 aligned_alloc 等内存分配函数来实现对内存的分配功能. 1)malloc 函数原型如下: void * ma ...

  8. C语言动态内存管理和动态内存分配函数

    给变量分配内存空间可分为静态内存分配和动态内存分配. 静态内存分配属于编译时给变量分配的空间,动态分配属于在程序运行时给变量分配的空间 静态分配属于栈分配,动态分配属于堆分配 运行效率上,静态内存比动 ...

  9. linux内核函数kmalloc,Linux内核内存分配函数之devm_kmalloc和devm_kzalloc

    本文介绍Linux内核内存分配函数devm_kmalloc()和devm_kzalloc(). 一.devm_kmalloc 文件:drivers/base/devres.c,定义如下: /** * ...

最新文章

  1. 2016年第七届蓝桥杯决赛Java本科B组试题解析
  2. BugkuCTF-Crypto题杰斐逊
  3. Spark基础学习笔记07:搭建Spark HA集群
  4. 震惊!99%的网络工程师都不知道的组播问题
  5. 如何使用 Numbers 筛选出特定种类的资料?
  6. python去除停用词_如何从gensim中的文档中删除停用词?
  7. ukey网络连接异常_Ukey的各种操作,你知道吗?
  8. 新闻发布系统数据库设计
  9. 新颖的基于物联网毕业设计题目50例
  10. 对接京东平台的第一篇
  11. discuz仿163k_Discuz模板-仿163k地方门户系统整站源码带数据
  12. 数学公式编辑器:MathType 7 for mac
  13. 差分放大电路的基本工作原理是什么//2021-2-18
  14. pg_hba.conf 中 md5 和 scram-sha-256 的区别
  15. PRML之Approximate Inference
  16. 获取苏宁易购商品信息操作详情
  17. doc 转 docx
  18. 研发部门压力管理探讨
  19. CF1066D Boxes Packing
  20. 6款常见的无人机仿真开发平台(附超详细特点功能对比)

热门文章

  1. Nacos 1.0.0 GA,架构、功能与 API 设计全面重构
  2. Node.js Stream(流) 简单易懂全解析
  3. asp.net Web API 身份验证 不记名令牌验证 Bearer Token Authentication 简单实现
  4. shell中判断空字符串和有趣的空字符串
  5. 关于向Mybatis传递多个参数进行SQL查询的用法
  6. iOS开展——全球应对MotionEvent
  7. Digital Image Processing 学习笔记3
  8. 防火墙iptables之常用脚本
  9. 无向图的最短路径求解算法之——Dijkstra算法
  10. [导入][翻译]匈牙利命名法的缺点