由於設備驅動存在錯誤、或者硬件存在問題,抑或是操作系統本身的原因,當系統遇到無法恢復的內核模式錯誤時,Windows會顯示臭名卓著的“藍屏死機”,隨後強行中止系統,以防止磁盤出現數據沖突,同時根據系統配置的情況,還會把部分或者全部的物理內存寫入到一個故障轉儲文件(crash dump file)。內存轉儲文件很有用,因為當我們死機後重啟系統時,微軟的在線故障分析服務(OCA)可以對其進行分析,以便找到問題的根源。如果我們願意,還可以自己用Microsoft Debugging Tools for Windows自己進行故障分析。
盆盆評注:有關如何用Debug工具分析系統故障的知識,可以參考張銀魁老師的Webcast。
然而舊版本的Windows,直到會話管理器進程(%Systemroot%System32Smss.exe)對頁面文件進行初始化以後,才可以啟用故障轉儲文件的支持。也就是說,在這以前,如果發生了嚴重的系統故障而導致系統藍屏,並不會生成轉儲文件。而大量設備驅動程序是在 Smss.exe進程啟動之前進行初始化,所以早期的系統故障並不會觸發轉儲文件的創建,所以對這些故障進行排錯就非常困難。
盆盆評注:有關Windows 2000/XP啟動過程的介紹,可以參考張銀魁老師的Webcast。
而Windows Vista則大大提前了可以創建轉儲文件的時間。現在,在所有啟動類型為“boot”的驅動程序啟動以後,而在所有啟動類型為“system”的驅動程序啟動以前,就可以初始化轉儲文件的支持。有了這個改進,當我們在系統引導階段遇到死機崩潰的故障,微軟OCA服務就可以幫助診斷這個問題。而且, Windows Vista以64KB的塊級別往轉儲文件裡填充數據,而老版本的Windows則是以4KB為單位。這樣大容量的內存轉儲文件,就能夠以十倍的速度生成。
盆盆評注:啟動類型為“boot”,是指由ntldr或者引導管理器加載的驅動程序。這些驅動程序比較重要,如果沒有啟動的話,Windows將無法繼續引導。啟動類型為“system”,是指內核初始化過程中啟動的驅動程序。
在Windows Vista中,應用程序的故障處理也得到了很好的改進。在舊版本的Windows中,當應用程序發生故障時,會執行一個專門的處理程序(unhandled exception handler),以對這種無法正常處理的例外進行處理。例外處理程序會加載微軟的應用程序錯誤報告(AER)進程(%Systemroot% System32Dwwin.exe),並且顯示對話框,提示該程序出錯,並詢問是否需要把錯誤報告發送給微軟。然而,如果該進程在崩潰時,主線程的堆棧被破壞,例外處理程序會在執行時崩潰,導致其進程被內核終止,結果是程序窗口一閃而過,根本沒有顯示任何錯誤報告對話框。
Windows Vista則將錯誤處理從崩潰進程的上下文中移走,而交由一個新的服務來處理,就是Windows Error Reporting(WER)服務。該服務運行在服務宿主進程中,是以DLL文件的形式實現的(%Systemroot%System32Wersvc.dll)。當應用程序發生故障時,它還是會執行例外處理程序,但是例外處理程序會給WER服務發送一個消息,而由WER服務加載WER錯誤報告進程(%Systemroot%System32 Werfault.exe),以顯示錯誤報告對話框。如果因為主線程的堆棧被破壞而導致例外處理程序崩潰,例外處理程序就會反復地執行崩潰、崩潰執行,最終把線程所有堆棧空間消耗干淨,當內核處於這個狀態的時候,就會給WER服務發送故障通知消息。
盆盆評注:服務宿主進程,就是指svchost進程。
我們可以在以下四張圖片中看到兩種實現方法的對比。這些圖片顯示Accvio.exe進程和錯誤報告進程之間的關系,Accvio.exe進程是一個故障測試程序,可以觸發一個應用程序崩潰。Windows Vista中新的錯誤處理機制意味著應用程序不再會悄無聲息地中止,而妨礙我們向微軟發送錯誤報告,以便幫助軟件開發商改進他們的產品。
Windows XP的應用程序錯誤處理
Windows XP的錯誤報告對話框
Windows Vista的應用程序錯誤處理
Windows Vista的錯誤報告對話框
盆盆評注:從圖1中可以看出,Windows XP的錯誤報告進程dwwin是由發生錯誤的應用程序所啟動,如果該應用程序的主線程堆棧被破壞,會導致無法彈出錯誤報告。而圖3顯示Windows Vista的錯誤報告進程WerFault是由svchost進程啟動的(實際上是由svchost進程裡的WER服務所加載),這樣的相對獨立機制,可以確保應用程序的錯誤都能被系統所捕獲。