使用 PoolMon 查找内核模式内存泄漏
如果怀疑存在内核模式内存泄漏,可以使用 PoolMon 工具确定哪个池标记与泄漏相关联。
PoolMon (Poolmon.exe) 按池标记名称监视池内存使用情况。 此工具包含在 Windows 驱动程序工具包 (WDK) 中。 有关详细信息,请参阅 PoolMon。
GFlags 池设置
某些 GFlags 设置(如特殊池)将影响内存池的使用方式。 有关详细信息,请参阅 GFlags 和 配置特殊池。
使用 PoolMon
PoolMon 标头显示总分页和非分页池字节数。 这些列显示每个池标记的池用法。 屏幕每隔几秒钟自动更新一次。 例如:
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 具有命令键,这些命令键根据各种条件对输出进行排序。 选择与每个命令关联的字母,以便使用数据。 每个命令需要几秒钟才能正常工作。
排序命令包括:
命令键 | 操作 |
---|---|
P | 将显示的标记限制为非分页池字节和/或分页池字节。 按该顺序重复按 P 循环遍历每个选项。 |
B | 按最大字节使用量对标记进行排序。 |
M | 按最大字节分配数对标记进行排序。 |
T | 按标记名称按字母顺序对标记进行排序。 |
E | 使显示内容在底部包含分页和未分页的总计。 |
A | 按分配大小对标记进行排序。 |
F | 按自由操作对标记进行排序。 |
S | 按分配和释放之间的差异对标记进行排序。 |
Q | 退出 PoolMon。 |
在 PoolMon 中显示驱动程序名称
可以使用 PoolMon /g 参数显示分配每个池标记的 Windows 组件和常用驱动程序的名称。 如果在具有特定标记的分配中发现问题,此功能可帮助你识别有问题的组件或驱动程序。
组件和驱动程序列在“Mapped_Driver”列中,即显示中最右侧的列。 Mapped_Driver 列的数据来自 pooltag.txt,该文件随 WDK 一起安装。
以下命令演示如何使用 /g 参数添加Mapped_Driver列。
poolmon /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"
显示特定池
使用 /i 参数显示以特定字符串开头的池标记,例如 Hid。
poolmon /iHid? /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"
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 实用工具查找内存泄漏的一种方法:
启动 PoolMon。
如果已确定泄漏发生在非分页池中,请选择 P 一次。 如果已确定它发生在分页池中,请选择 P 两次。 如果不知道,请不要选择 P,以便包括这两种类型的池。
选择 B 可按最大字节使用量对显示进行排序。
开始测试。 从屏幕复制输出,例如,拍摄屏幕截图并保存。
每半小时拍摄一次新的屏幕截图。 通过比较屏幕截图,确定哪些标记的字节正在增加。
停止测试并等待几个小时。 确定此时释放了多少标记。
通常,在应用程序达到稳定运行状态后,它会以相同的速率分配内存和可用内存。 如果分配内存的速度比释放内存快,则内存使用量会随着时间的推移而增长。 这通常表示内存泄漏。
解决泄漏问题
确定与泄漏关联的池标记后,你可能已获得有关泄漏的全部需要了解的内容。 如果需要确定分配例程的特定实例导致泄漏,请参阅 使用内核调试器查找内核模式内存泄漏。