使用 PoolMon 查找内核模式内存泄漏

如果怀疑存在内核模式内存泄漏,可以使用 PoolMon 工具确定与泄漏关联的池标记。

PoolMon (poolmon.exe) monitors pool memory usage by pool tag name. 此工具包含在 Windows 驱动程序工具包(WDK)中。 For more information, see PoolMon.

GFlags 池设置

Some GFlags settings such as Special Pool, can affect how memory pools are used. For more information, see GFlags and Configuring Special Pool.

Use PoolMon

PoolMon 标头显示总分页池字节和非分页池字节数。 列显示每个池标记的池用途。 显示每隔几秒钟自动更新一次。 For example:

Memory: 16224K Avail: 4564K PageFlts: 31 InRam Krnl: 684K P: 680K
Commit: 24140K Limit: 24952K Peak: 24932K Pool N: 744K P: 2180K

## Tag   Type     Allocs         Frees         Diff    Bytes             Per Alloc

CM       Paged     1283  ( 0)    1002  ( 0)     281    1377312   ( 0)    4901
Strg     Paged    10385 ( 10)    6658  ( 4)    3727     317952 ( 512)    85
Fat      Paged     6662  ( 8)    4971  ( 6)    1691     174560 ( 128)    103
MmSt     Paged      614  ( 0)     441  ( 0)     173      83456   ( 0)    482 

PoolMon 具有根据各种条件对输出进行排序的命令键。 若要更改数据的排序方式,请选择与特定排序命令关联的键盘快捷方式。 每个命令需要几秒钟才能影响显示。

下表列出了可用的排序命令:

Command key Operation
P Limit the tags shown to nonpaged pool bytes (P), paged pool bytes (P, P), or both (Enter). Repeatedly selecting P cycles through the options.
B 按最大字节使用量对标记进行排序。
M 按最大字节分配对标记进行排序。
T 按标记名称按字母顺序对标记进行排序。
E 显示显示底部的分页总计和非分页总计。
A 按分配大小对标记进行排序。
F 按免费作对标记进行排序。
S 按分配和释放之间的差异对标记进行排序。
Q Quit PoolMon.

在 PoolMon 中显示驱动程序名称

可以使用 PoolMon /g 参数显示 Windows 组件的名称和分配每个池标记的常用驱动程序。 如果发现分配中存在特定标记的问题,此功能可帮助你识别有问题的组件或驱动程序。

The components and drivers are listed in the Mapped_Driver column, the right-most column in the display. The data for the Mapped_Driver column comes from the pooltag.txt file installed with the WDK.

The following command shows the use of the /g parameter to add the Mapped_Driver column:

poolmon /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"

显示特定池

使用 /i 参数显示以特定字符串开头的池标记。

The following command shows the use of the /i parameter to add the string Hid:

poolmon /iHid? /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"

显示每隔几秒钟自动更新一次。 For example:

Memory:33473120K Avail:20055132K  PageFlts:     5   InRam Krnl:10444K P:1843072K
Commit:15035764K Limit:67027552K Peak:16677444K            Pool N:1023400K P:1955448K
System pool information

Tag    Type    Allocs         Frees        Diff   Bytes            Per Alloc Mapped_Driver

HidC   Paged    1667 (  0)    1659 (  0)     8      896 (     0)   112 [hidclass.sys - HID Class d 
HidC   Nonp    17375 (  0)   17256 (  0)   119    19808 (     0)   166 [hidclass.sys - HID Class d 
HidP   Nonp     1014 (  0)     998 (  0)    16     6704 (     0)   419 [hidparse.sys - HID Parser]

使用 PoolMon 实用工具查找内存泄漏

以下步骤演示了使用 PoolMon 实用工具查找内存泄漏的一种方法:

  1. Start PoolMon.

  2. 确定要检查的池类型:

    • Nonpaged pool: If you know the leak occurs in a nonpaged pool, select P once.

    • Paged pool: If you know the leak occurs in a paged pool, select P, P.

    • Both pools: If you're unsure about the leak source, select Enter, so both pool types are included. Don't select P.

  3. Select B to sort the display by Maximum byte use.

  4. 开始测试。

    • 复制并保存屏幕的输出,例如通过拍摄屏幕截图。

    • 每 30 分钟复制一次当前输出并将其保存到新文件。

  5. 有多个输出文件后,比较数据差异。 确定哪些标记的字节数正在增加。

  6. 停止测试并等待几个小时。 确定在此期间释放了多少标记。

通常,在应用程序达到稳定的运行状态后,它会以相同的速率分配内存和释放内存。 如果它分配的内存比释放内存快,则内存使用量会随着时间的推移而增加。 此行为通常表示内存泄漏。

解决泄漏问题

确定与泄漏关联的池标记后,可能具有有关泄漏的所有必要信息。 如果需要确定分配例程的特定实例导致泄漏,请参阅 使用内核调试器查找内核模式内存泄漏