当 Windows 发生蓝屏时,如果设置正确,系统会将发生故障时内核内存的关键信息写入一个文件,这个文件叫做转储文件(Dump File),通常以.dmp为后缀。

本文将介绍如何使用 WinDbg 来分析系统蓝屏的原因;

什么是 WindDbg

WinDbg 是微软官方提供的、功能强大的免费调试器,可用于分析故障转储、调试实时用户模式和内核模式代码,以及检查 CPU 寄存器和内存。

当程序崩溃、系统蓝屏或者行为异常,开发人员就会使用 WinDbg 来深入程序内部,查看其内存、寄存器等核心信息,从而精准定位问题的根本原因。

安装 WinDbg

直接访问官方的下载链接下载 WinDbg 安装程序,然后打开该文件并按提示进行操作;

或通过 Microsoft Store 安装 WinDbg:

或在命令行运行以下命令进行安装:

winget install Microsoft.WinDbg

分析蓝屏原因

1. 获取内核转储文件;方法可查看:

最好是将内核转储文件复制到另外一台正常运行的计算机上进行分析,以免中途出现蓝屏;

2. 安装并运行 WinDbg;

运行WinDbg
WinDbg 运行界面

3. 依次点击【文件】【Start debugging】【Open dump file】,选择要分析的转储文件,并【打开】;

使用WinDbg打开转储文件
使用WinDbg打开转储文件

4. 打开文件后,点击!analyze -v或者在输入框输入!analyze -v并运行;

WinDbg 会下载符号文件,建议在联网环境中运行;

有了符号文件,调试器就能显示清晰的函数名;

分析转储文件
分析转储文件

等待片刻后,你将看到一份详细的分析报告;因为篇幅有限,这里给出的示例不完整且进行了整理,只对关键字段进行解释;

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

KMODE_EXCEPTION_NOT_HANDLED (1e)
This is a very common BugCheck.  Usually the exception address pinpoints
the driver/function that caused the problem.  Always note this address
as well as the link date of the driver/image that contains this address.
Arguments:
Arg1: ffffffffc0000005, The exception code that was not handled
Arg2: fffff8022506decf, The address that the exception occurred at
Arg3: 0000000000000001, Parameter 0 of the exception
Arg4: ffff8003d323b812, Parameter 1 of the exception

其中KMODE_EXCEPTION_NOT_HANDLED (1e)指明了蓝屏的错误代码和名称;1e0x0000001e

BUGCHECK_CODE:  1e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: fffff8022506decf
BUGCHECK_P3: 1
BUGCHECK_P4: ffff8003d323b812
FILE_IN_CAB:  073125-225953-01.dmp
FAULTING_THREAD:  fffff8020f56d840
EXCEPTION_PARAMETER1:  0000000000000001
EXCEPTION_PARAMETER2:  ffff8003d323b812
WRITE_ADDRESS: Unable to get NonPagedPoolStart
Unable to get NonPagedPoolEnd
Unable to get PagedPoolStart
Unable to get PagedPoolEnd
 ffff8003d323b812 
BLACKBOXBSD: 1 (!blackboxbsd)
BLACKBOXPNP: 1 (!blackboxpnp)
CUSTOMER_CRASH_COUNT:  1
  • BUGCHECK_CODE:蓝屏错误代码
  • BUGCHECK_P1 - P4:蓝屏时传递给系统崩溃处理程序的四个参数,专业人员可通过他们更加精准的定位问题;
  • FAULTING_THREAD:蓝屏时正在执行的线程 ID;

此处删除了 HEX 数据,并对行数进行了编号;

STACK_TEXT:  
1 : nt!KeBugCheckEx
2 : nt!KiFatalExceptionHandler+0x22
3 : nt!RtlpExecuteHandlerForException+0xf
4 : nt!RtlDispatchException+0x430
5 : nt!KiDispatchException+0x144
6 : nt!KiExceptionDispatch+0xc2
7 : nt!KiPageFault+0x42e
8 : dxgkrnl!DXGADAPTER::PowerRuntimeComponentActiveCallback+0x193
9 : dxgkrnl!DxgkPowerRuntimeComponentIdleCallback+0x46
10: nt!PopFxIdleWorker+0x7f
11: nt!PopFxIdleComponent+0x105
12: nt!PoFxIdleComponent+0xe
13: dxgkrnl!DXGADAPTER::ProcessComponentIdleList+0x150
14: dxgkrnl!DxgkpComponentIdleListTimerDpc+0xc
15: nt!KiProcessExpiredTimerList+0x159
16: nt!KiRetireDpcList+0x4a7
17: nt!KiIdleLoop+0x5a

STACK_TEXT是调用堆栈的文本表示。它显示了在发生崩溃的那一刻,CPU 正在执行的函数,以及是哪些函数依次调用了它,一直回溯到线程的起点。

在此例中,最重要的行是 7、8 和 9;此问题是因为dxgkrnl导致的;dxgkrnl是 DirectX 图形内核驱动程序;

PROCESS_NAME:  System
SYMBOL_NAME:  dxgkrnl!DXGADAPTER::PowerRuntimeComponentActiveCallback+193
MODULE_NAME: dxgkrnl
IMAGE_NAME:  dxgkrnl.sys
IMAGE_VERSION:  10.0.17763.1971
FAILURE_BUCKET_ID:  AV_W_dxgkrnl!DXGADAPTER::PowerRuntimeComponentActiveCallback

报告中最重要的部分,其中:

  • PROCESS_NAME:如果蓝屏是由一个用户模式的进程触发的,这里会显示进程名;
  • SYMBOL_NAME:故障指令对应的符号信息
  • MODULE_NAME、IMAGE_NAME:模块名称;如果直接显示了.sys文件名,大概率它就是元凶;
  • FAILURE_BUCKET_ID:这是微软用于在数据库中对类似错误进行自动分类和统计的唯一标识符。如果你在网上搜索这个 ID,很可能找到官方的解决方案或遇到相同问题的用户;

解决方案

限时免费分析

为了收集导致蓝屏的常见原因,现提供免费的分析服务;

你可将内核转储文件发送到邮箱:hocn@woomua.com;作者收到邮件后将对其进行分析并回复分析报告。

说明

  • 邮件主题请注明【蓝屏分析】;
  • 请尽量详细的描述问题(比如在某个特定条件下触发蓝屏),并提供【小内存转储文件】;多个文件请压缩到一个文件中,文件大小不要超过 10MB,使用常用的压缩格式;
  • 由于导致蓝屏的原因可能非常复杂(特别是硬件问题),分析结果是根据转储文件记录的信息得出,并不一定是蓝屏的真正原因;
  • 作者回复的信息仅供参考;使用这些信息造成的后果需自行承担!
  • 分析过程可能会被写成文章发表,您的转储文件可能会被用作示例展示;

你可通过分析报告中的BUGCHECK_CODEPROCESS_NAMEMODULE_NAMEIMAGE_NAME等信息大致了解是由什么进程、驱动引起的,卸载问题驱动并从官网下载安装最新驱动大概率可以解决问题。

你也可以通过搜索FAILURE_BUCKET_ID字段给出的信息,查找官方是否为此问题提供了解决方案,或者找到碰到相同问题的人。