驱动程序内存池泄漏导致系统死机的调试
最近S告诉我说电脑老是死机,现象就是用着用着系统就无响应了,键盘鼠标无响应。每周出现上1-2次。。由于环境拿不到没法现场调试,所以只能获取dump来调试了。
对于系统hang住,要获取内存转储可通过键盘手动触发,系统无响应的时候,键盘CTRL+SCROLL LOCK+SCROLL LOCK,就可以生成dump,配置可参考这个:http://support.microsoft.com/kb/244139。
接到Dump后调试一把,windbg显示原因是键盘驱动,Probably caused by : i8042prt.sys ( i8042prt!I8xProcessCrashDump+237 ),当然了,蓝屏就是按出来的。
再看一下内存池的使用
kd> !vm
*** Virtual Memory Usage ***
Physical Memory: 63358 ( 253432 Kb)
Page File: \??\C:\pagefile.sys
Current: 393216 Kb Free Space: 191636 Kb
Minimum: 393216 Kb Maximum: 786432 Kb
Available Pages: 5596 ( 22384 Kb)
ResAvail Pages: 21461 ( 85844 Kb)
Locked IO Pages: 48 ( 192 Kb)
Free System PTEs: 236827 ( 947308 Kb)
Free NP PTEs: 0 ( 0 Kb)
Free Special NP: 0 ( 0 Kb)
Modified Pages: 641 ( 2564 Kb)
Modified PF Pages: 641 ( 2564 Kb)
NonPagedPool Usage: 24926 ( 99704 Kb)
NonPagedPool Max: 24927 ( 99708 Kb)
********** Excessive NonPaged Pool Usage *****
PagedPool 0 Usage: 5233 ( 20932 Kb)
PagedPool 1 Usage: 875 ( 3500 Kb)
PagedPool 2 Usage: 878 ( 3512 Kb)
PagedPool Usage: 6986 ( 27944 Kb)
PagedPool Maximum: 50176 ( 200704 Kb)
********** 102904 pool allocations have failed **********
Shared Commit: 17737 ( 70948 Kb)
Special Pool: 0 ( 0 Kb)
Shared Process: 2593 ( 10372 Kb)
PagedPool Commit: 6986 ( 27944 Kb)
Driver Commit: 2869 ( 11476 Kb)
Committed pages: 107348 ( 429392 Kb)
Commit limit: 154891 ( 619564 Kb)
其中内核非换页池用光了,这估计是死机无响应的直接原因。
NonPagedPool Usage: 24926 ( 99704 Kb)
NonPagedPool Max: 24927 ( 99708 Kb)
很遗憾,生成这个dump的时候S的机器没有启用内核池标签,所以这个dump无法知道是谁用了最多的内存池。于是我又发个工具帮助打开池tag,下次获取的dump才更有意义。
同时,上面这个dump的其他信息显示系统安装了RX和360的驱动,有比较大的嫌疑,所以引入DriverVerifier可以更快的确认问题。有问题的机器上使用DriverVerifier(开始运行输入Verifier),选择对内核驱动程序进行池跟踪(Pool Tracking)检查:
接着在驱动程序列表中选中所有的RX和360的驱动,一共11个
重启系统,果然蓝屏了。。再次打开Dump这次显示是RX的内核驱动HookNtos.sys,说明它存在池泄漏的Bug.
STACK_TEXT:
f96c7acc 80994673 000000c4 0000003c cdefb104 nt!KeBugCheckEx+0x1b
f96c7aec b9945698 cdefb104 000f0000 82317040 nt!VerifierReferenceObjectByHandle+0x6c
WARNING: Stack unwind information not available. Following frames may be wrong.
f96c7b14 b9945715 00000000 f96c7b24 00000000 HookNtos+0x2698
f96c7d48 808077ec cdefb104 7c94da87 000d8b58 HookNtos+0x2715
f96c7d48 7c92eb94 cdefb104 7c94da87 000d8b58 nt!KiFastCallEntry+0xf8
018efe40 00000000 00000000 00000000 00000000 0x7c92eb94
这次蓝屏的时候池的使用情况:
NonPagedPool Usage: 11110 ( 44440 Kb)
NonPagedPool Max: 24927 ( 99708 Kb)
虽然没有满,但是用了将近一半。。也不正常。所以要看看都是谁在用:
kd> !poolused 2
Sorting by NonPaged Pool Consumed
Pool Used:
NonPaged Paged
Tag Allocs Used Allocs Used
GetGlobalValue: unable to get nt!KeNumberProcessors type size
SaMo 97 25170576 0 0 UNKNOWN pooltag 'SaMo', please update pooltag.txt
Wdm 765 13461944 22 1688 WDM
Ddk 536 1144104 6 336 Default for driver allocated memory (user's of ntddk.h)
DmaB 34 729088 0 0 UNKNOWN pooltag 'DmaB', please update pooltag.txt
063p 6 247384 0 0 UNKNOWN pooltag '063p', please update pooltag.txt
。。。
这是由NonePagedPool使用由多到少的排序,这几个都比较可疑:SaMo ,Ddk ,063p 我怎么知道这些池Tag对应哪些驱动呢?使用Poolmon(win2k3DDK中的工具),使用Poolmon /c 参数后它将扫描所有System32\Drivers目录下的驱动文件,并生成一个驱动和它使用Tag的一个对应清单,在这台机器上这里查到的是:
Ddk - HookHelp
Ddk - HookSys
Ddk - HookCont
Ddk - HOOKREG
Ddk - HookNtos
Ddk - rfwbase
PIAM - rfwbase
SaMo - SafeboxKrnl
Ddk - SafeboxKrnl
063p - 360AntiARP
这次我的推断是,周老大的SafeboxKrnl(SaMo)在这里使用了最多的非换页池,周老大联手RX的一堆驱动一起(Ddk)取得第三,360AntiARP(063p)也挤进前五。非换页池是Windows内核使用的,内存池耗尽或者不足的时候会影响系统稳定性。
为了验证,系统正常运行时,我使用Poolmon在这台机器上记录了日志,这是实时的日志:
Tag Type Diff Bytes Per Alloc Mapped_Driver
SaMo Nonp 86 19824384 230516 [SafeboxKrnl]
Wdm Nonp 771 13464208 17463 [cinemst2][cpqdap01][nikedrv][rio8drv][riodrv][tsbvcap][drmk]
Ddk Nonp 1473 996960 676 [ptilink][nv4_mini][basetdi][HookHelp][HookSys][HookCont]
DmaB Nonp 34 729088 21443 [ALCXWDM]
File Nonp 1982 336496 169 [<unknown> - File objects]
Thre Nonp 505 319160 632 [nt!ps - Thread objects]
063p Nonp 6 247384 41230 [360AntiARP]
。。。
,和系统蓝屏的时候差不太多。
至此推断的原因可能是:RX的一个驱动存在内存泄漏,在分配NonePagedPool后,卸载时没有去Free,加上有其他大亨也占用了很多NonePagedPool,所以NonePagedPool最终耗尽了,系统挂起。由于暂时还没有拿到系统死机时带有池标签的Dump文件,所以还不能最终确认。但DriverVerifier检查出的池泄漏的结论是一定的。
P.S. 至于为什么系统在装了杀软后会变慢,这也是其中原因之一了。
强帖留名
未分页内存没有到256MB呢吧?才90多MB?
如果是未分页内存导致的down机,是没有dump的。。。
我以前专门测试过,把一个win2003 32位的nonpagedpool 搞到250MB以上
眼睁睁就不动了。。。没有dump生成。。。。
windows直接歇菜。。。
@PC
Q:未分页内存没有到256MB呢吧?才90多MB?
A:不同系统的池上限是不一定的,Windows会依据系统实际内存大小进行分配,在上述第一个dump的机器上(耗尽挂起),非换页池只有99708Kbytes(99M),在调试器中直接查看系统非换页池的内核变量:
kd> dd mmmaximumnonpagedpoolinbytes l1
80887ec4 0615f000
kd> ? 80887ec4
Evaluate expression: -2138538300 = 80887ec4
kd> ? 615f000
Evaluate expression: 102100992 = 0615f000
102100992/1024=99708 <----这个就是当前实际的非换上限,如果你先看你现在机器上池上限是多少,可以用ProcessExplorer,配上Symbols后在System Infomation里就可以看到了:Paged limit和Nonpaged limit
Q:如果是未分页内存导致的down机,是没有dump的。。。
A:是的,因为系统挂起了,所以要手动用键盘生成dump
见这个链接:http://support.microsoft.com/kb/244139
对系统和键盘类型有一定要求(比如ps2口)
oh,my god...