奇妙的系统性能问题(2)

引用注明>> 【作者:张佩】【原文:www.YiiYee.cn/blog

这篇文件是对上一篇《奇妙的系统性能问题》的补充。我在经历那次性能陡降问题困扰的过程中,还碰到了一次BSOD。当蓝屏发生的时候,我甚至是兴奋的。因为在此之前,我一直都认为问题是系统或软件模块导致的。而蓝屏正好是分析的切入点。所以当分析了这个dump后,我立刻扭转了方向,判断认为:确实是磁盘坏了。

这个结论是正确的,但却不完备的。因为最后的结果是磁盘并没有坏,而是受到了外部环境的干扰。

这个dump文件弥足珍贵,因为正常情况下,这种伤硬盘的实验我们是不会主动去做的。所以这个dump文件完全得于碰巧,在此进行分析。

1: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

KERNEL_DATA_INPAGE_ERROR (7a)
The requested page of kernel data could not be read in.  Typically caused by
a bad block in the paging file or disk controller error. Also see
KERNEL_STACK_INPAGE_ERROR.
If the error status is 0xC000000E, 0xC000009C, 0xC000009D or 0xC0000185,
it means the disk subsystem has experienced a failure.
If the error status is 0xC000009A, then it means the request failed because
a filesystem failed to make forward progress.
Arguments:
Arg1: ffffc00006694e90, lock type that was held (value 1,2,3, or PTE address)
Arg2: ffffffffc0000185, error status (normally i/o status code)
Arg3: 0000000042bde860, current process (virtual address for lock type 3, or PTE)
Arg4: fffff960002fdcc0, virtual address that could not be in-paged (or PTE contents if arg1 is a PTE address)

Debugging Details:
------------------

ERROR_CODE: (NTSTATUS) 0xc0000185 - The I/O device reported an I/O error.

DISK_HARDWARE_ERROR: There was error with disk hardware

BUGCHECK_STR:  0x7a_c0000185

DEFAULT_BUCKET_ID:  CODE_CORRUPTION

PROCESS_NAME:  explorer.exe

CURRENT_IRQL:  0

根据Windbg的Help文档,bug check的4个参数分析如下:

Parameter

Description

1 The address of the page table entry (PTE)
2 The error status (usually an I/O status code)
3 The PTE contents
4 The faulting address

Arg1: ffffc00006694e90, PTE地址

Arg2: ffffffffc0000185, 错误码

Arg3: 0000000042bde860, PTE,即参数1所在地址的值

Arg4: fffff960002fdcc0, 需要被page in但发生错误的地址

下面是一些详细信息:

1: kd> dd ffffc00006694e90 L1
ffffc000`06694e90  42bde860
1: kd> !error 0xc0000185
Error code: (NTSTATUS) 0xc0000185 (3221225861) - The I/O device reported an I/O error.

当前的调用栈如下:

1: kd> kn
 # Child-SP          RetAddr           Call Site
00 ffffd000`26675b78 fffff802`bf64d0ea nt!DbgBreakPointWithStatus 
01 ffffd000`26675b80 fffff802`bf64c9fb nt!KiBugCheckDebugBreak+0x12 
02 ffffd000`26675be0 fffff802`bf5c4da4 nt!KeBugCheck2+0x8ab 
03 ffffd000`266762f0 fffff802`bf5ed973 nt!KeBugCheckEx+0x104 
04 ffffd000`26676330 fffff802`bf4da190 nt!MiWaitForInPageComplete+0x11065f 
05 ffffd000`26676420 fffff802`bf4b318f nt!MiIssueHardFault+0x184 
06 ffffd000`266764e0 fffff802`bf5cef2f nt!MmAccessFault+0x3cf 
07 ffffd000`26676620 fffff960`002fdcc0 nt!KiPageFault+0x12f 
08 ffffd000`266767b8 fffff960`00199320 win32k!CleanupShadow
09 ffffd000`266767c0 fffff960`001833db win32k!xxxFreeWindow+0x9ec
0a ffffd000`26676850 fffff960`0019ab61 win32k!xxxDestroyWindow+0x30f
0b ffffd000`26676910 fffff960`00174968 win32k!xxxRemoveShadow+0x7d
0c ffffd000`26676940 fffff960`00174b90 win32k!xxxSendChangedMsgs+0x230
0d ffffd000`266769c0 fffff960`001611ac win32k!xxxEndDeferWindowPosEx+0x204
0e ffffd000`26676a80 fffff960`0014c675 win32k!xxxSetWindowPosAndBand+0xc0
0f ffffd000`26676b10 fffff960`0014c26a win32k!xxxSetWindowPos+0x29
10 ffffd000`26676b60 fffff960`0014b86f win32k!xxxShowWindow+0x1a6
11 ffffd000`26676bf0 fffff802`bf5d04b3 win32k!NtUserShowWindow+0xab
12 ffffd000`26676c40 00007ffa`2e44119a nt!KiSystemServiceCopyEnd+0x13 
13 00000000`0335f448 00007ffa`2a4554cc USER32!ZwUserShowWindow+0xa 
14 00000000`0335f450 00000000`01139c00 Comctl32!InitCommonControls+0x18cc
15 00000000`0335f458 00000000`0001009a 0x1139c00
16 00000000`0335f460 00000000`00000001 0x1009a
17 00000000`0335f468 00000000`00000001 0x1
18 00000000`0335f470 00000000`00000001 0x1
19 00000000`0335f478 00007ffa`2a48252f 0x1
1a 00000000`0335f480 00000000`000100be Comctl32!CCEnableScrollBar+0x4f83
1b 00000000`0335f488 00000000`0001009a 0x100be
1c 00000000`0335f490 00000000`fffffdf6 0x1009a
1d 00000000`0335f498 000024ed`e852e2d2 0xfffffdf6
1e 00000000`0335f4a0 00000000`00000006 0x000024ed`e852e2d2
1f 00000000`0335f4a8 00007ffa`2a4824e1 0x6
20 00000000`0335f4b0 00000000`00000000 Comctl32!CCEnableScrollBar+0x4f35

这个调用栈可以被简单地分成三个部分:

Frame 0-7:这是处理页错误的部分,处理过程中发生了硬件错误(Hardware Fault),最后调用KeBugCheckEx产生蓝屏。

Frame 8-12:这是在内核的Win32k模块中进行绘图操作的部分。

Frame 13-20:这是Explorer进程的用户模块部分。

重要的是第一和第二部分。为什么会从Win32k执行,转入页错误处理呢?如果没有页错误处理,蓝屏是不会立刻发生的。看一下第二部分最上面那个函数的地址:

1: kd> x win32k!CleanupShadow
fffff960`002fdcc0 win32k!CleanupShadow (void)

这个值正是bug check的第三个参数。这样问题就清晰了起来了:函数win32k!CleanupShadow所在的代码页已经被换出到页文件中,当调用到它的时候,系统必须把它所在的页文件换入系统内存中;在做换入操作的时候,可能是长时间震动而导致了物理磁片损坏,磁盘驱动无法从磁盘中读取相关页的内容,导致了蓝屏。

从系统的角度来讲,它可以认为Win32k的镜像文件已经被破损了。这时候如果检查一下win32k模块的镜像文件完整性,错误就多得吓人了。

1: kd> !chkimg win32k -d
    fffff960001906ff-fffff9600019070e  16 bytes - win32k!W32pServiceTable+fff
	[ ff a0 83 40 00 60 f9 ff:02 86 4f 75 01 40 fa 95 ]
    fffff96000190710-fffff9600019071a  11 bytes - win32k!W32pServiceTable+1010 (+0x11)
	[ a0 83 40 00 60 f9 ff ff:00 b5 0f 02 00 47 62 00 ]
    fffff9600019071c-fffff9600019072a  15 bytes - win32k!W32pServiceTable+101c (+0x0c)
	[ 60 f9 ff ff a0 83 40 00:00 43 27 01 c0 dd 0f 02 ]
    fffff9600019072c-fffff96000190736  11 bytes - win32k!W32pServiceTable+102c (+0x10)
	[ 60 f9 ff ff a0 83 40 00:00 a2 0e 01 00 c5 75 01 ]
    fffff96000190738-fffff9600019073a  3 bytes - win32k!W32pServiceTable+1038 (+0x0c)
	[ a0 83 40:00 00 00 ] 
    // …省略
4756 errors : !win32k (fffff960001906ff-fffff960002fdfff)

这表明磁盘的质量很重要,要是在使用过程中磁盘出了问题,如果运气不差的话,发生在普通文件区域,最多是文件破损导致无法读写;但如果碰巧是页文件所在磁盘区出了问题,那么系统会很快死翘翘的。

5,482 total views, 1 views today

《奇妙的系统性能问题(2)》有4个想法

  1. 您好,

    上面您說到:
    函數win32k!CleanupShadow所在的代碼頁已經被換出到頁文件中.

    請問是怎麼看出來的? 是因為預期為0000000042bde860, 但實際上卻是fffff960`002fdcc0, 兩者不同所得的結論嗎?

    謝謝.

    1. 可以从call stack的后续函数看出。win32k!CleanupShadow偏移为0,说明没有执行哪怕一条此函数的指令。然后是页错误处理。由此可推理而出。

kazuya进行回复 取消回复

电子邮件地址不会被公开。