在默认情况下,所有的Windows系统都被设置为:当系统崩溃时,系统总是试图记录下有关当前系统的状态的信息。你可以通过用户界面看到这些设置,做法是,打开控制面板中的System工具,然后在System Properties对话框中,点击Advanced标签,然后点击Startup And Recovery按钮.
对于一次系统崩溃,以下三种层次的信息可以被记录下来。
完全内存转储  完全内存转储包含了在崩溃时刻所有的物理内存。这种转储类型要求页面文件至少是物理内存的大小再加上1MB(用于记录头信息)。因为在大内存的系统上,它要求一个非常大的页面文件,所以,这种类型的转储文件是最少见的设置。Windows NT 4只支持这种类型的崩溃转储文件。这也是Windows Server系统的默认设置。
内核内存转储  内核内存转储只包含了在崩溃时刻位于物理内存中的内核模式读/写页面。这种转储类型并不包含属于用户进程的页面。然而,因为只有内核模式的代码才可以直接导致Windows崩溃,所以,用户进程页面通常对于崩溃调试来说是不必要的。而且,所有与崩溃转储分析有关的数据结构,包括当前运行进程的列表、当前线程的栈,以及已加载驱动程序的列表,都被保存在非换页的内存中,它们也被记录在内核内存转储中。没有很好的办法来预测内核内存转储的大小,因为它的大小取决于该机器上操作系统和所有活动驱动程序已经分配的内核模式内存的数量。
小内存转储  小内存转储(在Windows Professional上,这是默认设置)也称为小转储(minidump)或分类优先转储(triage dump),它的大小为64KB(在64位系统上为128KB)。它包含了停止代码和参数、已加载的设备驱动程序的列表、描述当前进程和线程的数据结构(称为EPROCESSETHREAD,见第6章的描述),以及引起此次崩溃的线程的内核栈。
虽然完全内存转储是其他选项的超集,但是,它的缺点是,其大小达到了一个系统上所有物理内存的总量,因而变得很不实用。大的服务器系统有几GB物理内存的情形并不罕见,这样会导致崩溃转储文件太大,以致无法上载到FTP服务器上,或者被刻到CD上。因为在绝大多数的崩溃分析过程中,用户模式的代码和数据并没有被使用到(因为系统崩溃是由于内核内存中存在问题而引起的,并且,系统数据结构驻留在内核内存中),所以,在完全内存转储中保存的许多数据与分析并不相关,因而它们纯粹浪费了转储文件的空间。最后一个缺点是,引导卷(\Windows目录所在的卷)上的页面文件的大小必须至少等于该系统中物理内存的数量再加上1MB。由于在一般情况下,所要求的页面文件的大小与实际物理内存的数量成反比例,因此,这一需求可能强迫页面文件变得不必要的大。你应该考虑小内存转储和内核内存转储这两种选项所提供的好处。
小转储的一个好处是它的尺寸非常小,这使得它非常便于交换,比如通过电子邮件来交换。而且,每一次崩溃都会在\Windows\Minidump目录中生成一个文件,该文件有一个惟一的文件名,是由字符串“Mini”加上日期和一个序列号(比如Mini082604-01.dmp)构成的。小转储的一个缺点是,为了对它们进行分析,你在分析时必须使用与生成该转储的系统上用到的相同映像文件(最起码,Ntoskrnl.exe必须是相符的版本,以便进行最基本的分析)。如果你想在一个不同于生成某个转储的系统上分析该转储,那么这可能是一个问题。然而,Microsoft的符号服务器包含了Windows XP系统及以后版本的映像(和符号),所以,你可以在调试器中设置映像路径,使它指向符号服务器,于是,调试器就会自动下载所需要的映像(当然,Microsoft的映像服务器并不包含你所安装的第三方驱动程序的映像)。
一个更重要的缺点是,由于在转储文件中只保存了很有限的数据,这可能会使得有效的分析难以进行。另外,即使你配置一个系统,并让它生成内核崩溃转储或完全崩溃转储,你也可以获得小转储的好处,你只需用Windbg来打开一个大的崩溃转储,然后用.dump /m命令提取出一个小转储。注意,在Windows XPWindows Server 2003上,小转储是自动创建的,即使系统被设置为完全转储或内核转储。
注: 你可以在Livekd中,利用.dump命令生成当前活动系统的一个内存映像,因而你无需停止系统就可以离线地分析该系统。若一个系统虽然出现了一个问题但仍然在提供服务,而且你想在不打断该服务的情况下诊断此问题,那么,此时这种方法非常有用。结果得到的崩溃映像并不是完全一致的,因为不同内存区域的内容反映的是不同时间点上的情形,但是它可能包含了对于分析非常有用的信息。
内核内存转储方案提供了一种更切合实际的中间选择。因为它包含了所有的属于内核模式的物理内存,所以,它与完全内存转储具有同样层次的可分析数据,但是它省略了通常不相关的用户模式数据和代码,因此,它可以比完全内存转储小得多。举例来说,在一个具有256MB RAMWindows XP系统上,一个内核内存转储的大小为34MB;在另一个具有1.5GB RAMWindows XP系统上,一个内核内存转储达到了72MB
当你配置内核内存转储的时候,系统检查页面文件是否足够大(见表14.1),但是,这些只是估计的大小值,因为没有办法可以预测一个内核内存转储的大小。之所以无法预测一个内核内存转储的大小,是因为它的大小取决于在崩溃时刻该机器的操作系统和所有活动驱动程序正在使用的内核模式内存的数量。
14.1  针对内核转储的默认最小页面文件大小
系统内存的大小
针对内核转储的最小页面文件大小
< 128 MB
50 MB
< 4 GB
200 MB
< 8 GB
400 MB
>= 8 GB
800 MB
因此,在崩溃发生时,因为页面文件太小而无法容纳一个内核转储,这是有可能的。如果你想要看一看自己系统上一个内核转储的大小,那么,你可以手工强制来一次崩溃,做法是,配置相应的选项以便你可以从控制台发起一次手工系统崩溃,或者使用本章后面将要讲述的Notmyfault工具(本章后面讲述了这两种方法)。当你重新引导时,你可以进行检查,以确保一个内核转储已经生成了,而且,你也可以检查它的大小以估算出你的引导卷页面文件应该设置为多大。为保险起见,在32位系统上,你可以选择2GB1MB大小的页面文件,因为2GB是所有可用内核模式地址空间的最大值。
最后,即使系统成功地在崩溃时刻将崩溃转储记录到页面文件中了,它还必须有足够的空闲磁盘空间来提取此转储文件。如果没有足够的磁盘空间,那么,崩溃转储就丢失了,因为在页面文件中用于保存崩溃转储的空间被释放了,随着系统开始使用此页面文件,这部分空间也将被覆盖掉。如果你在引导卷上没有足够的空间来保存memory.dmp文件,那么,你可以通过如图14.3中显示的对话框来选择任何其他本地硬盘上的某一个位置。
崩溃转储的生成
当系统引导时,它读取注册表值HKLM\System\CurrentControlSet\Control\CrashControl,以检查当前配置的崩溃转储选项。如果已经配置了一个转储,那么,它把用来写引导卷的磁盘小端口驱动程序在内存中做一份拷贝,并且赋予它一个与小端口相同的名称,前面加上“dump_”作为前缀。对于在写崩溃转储过程中涉及的组件,系统也计算它们的校验和,并且保存起来。这样的组件包括刚刚被拷贝的磁盘小端口驱动程序、执行崩溃转储写操作的I/O管理器函数,以及引导卷的页面文件在磁盘上的映射表。当KeBugCheckEx执行时,它再次计算这些组件的校验和,并且将新得到的校验和与引导时得到的校验和进行比较。如果两者不相符,那么它不再写崩溃转储文件,因为这样做可能会失败,或者破坏磁盘。如果两个校验和相匹配,那么,KeBugCheckEx直接将转储信息写到由页面文件占据的磁盘扇区中,从而绕过了文件系统驱动程序(它可能已被破坏,甚至正是它导致了系统崩溃)。
SMSS在引导过程中启用换页机制时,系统检查引导卷的页面文件,看是否存在一个崩溃转储,并且将页面文件中被崩溃转储所占据的那部分保护起来。这使得在引导的早期阶段,引导卷页面文件的部分或全部是不可用的,从而可能会导致发出通知以显示系统当前的虚拟内存过低。当然,这一条件只是暂时的。后来,仍然在引导过程中,Winlogon通过调用未文档化的NtQuerySystemInformation API来确定该页面文件中是否存在一个崩溃转储,如果存在崩溃转储,则激发Savedump进程(\Windows\System32\Savedump.exe),以便从该页面文件中提取出此崩溃转储,并且将它拷贝到最终的位置上。这些步骤如图14.4所示。
 windows崩溃转储文件_windows崩溃转储文件