操作系统(Operating System,简称OS)是计算机系统中的基本软件,它负责统一管理系统中的软硬件资源,为系统中运行的应用软件(applications)提供服务,是应用软件运行的基础。操作系统所提供的服务因操作系统的设计目的和使用环境不同而有所差异,但通常都包括文件管理、内存管理、进程管理、打印管理、网络管理等基本功能。除了这些功能外,如何支持调试也是操作系统设计的一项根本任务,从被调试对象角度来看,可以把操作系统的调试支持分为以下3个方面。
第一,对应用程序调试(Application Debugging)的支持,即如何简单高效地调试运行在系统中的各种应用程序。应用程序通常在操作系统分配的较低优先级下运行,其代码属于操作系统不信赖的代码。
第二,对设备驱动程序调试(Device Driver Debugging)的支持,设备驱动程序或其他运行在内核模式的模块是操作系统的可信赖代码,通常与操作系统运行在同一个优先级下和同一个地址空间中,因此调试这些模块通常与调试应用程序有很大不同。
第三,对操作系统自身调试的支持,即如何调试操作系统的各个组成部分。例如调试正在开发过程中的系统模块,以及定位产品发布后出现的系统故障。
调试器(Debugger)是软件调试的最重要工具,使用调试器调试是解决复杂软件问题的首选途径。但是在某些情况下(比如产品发布后发生在用户环境中的问题),并不具备使用调试器调试的条件,这时就必须考虑如何在没有调试器的情况下进行调试。从这个意义上讲,对于以上每类调试对象(任务),还必须考虑两种情况。
第一,使用调试器的调试,即通过有效的模型和系统机制来支持调试器器软件操纵和访问被调试对象。
第二,不使用调试器的调试,即通过操作系统的基础服务,支持软件实现各种不依赖于调试器的调试途径,比如错误提示、事件追踪、日志和错误报告等。
综合以上分析,可以把操作系统的调试支持归纳为如下表所示的6个问题。
|
使用调试器的调试 | 不使用调试器的调试 |
调试应用程序 | 如何使系统中的应用程序可以被调试器调试?(问题A) | 如何使系统中的应用程序在没有调试器时也具有很好的可调试性?(问题B) |
调试驱动程序 | 如何使系统中的驱动程序可以被调试器调试?(问题C) | 如何使系统中的驱动程序在没有调试器时也具有很好的可调试性?(问题D) |
调试操作系统自身 | 如何使操作系统自身的代码可以被调试器调试?(问题E) | 如何使系统本身在没有调试器时也具有很好的可调试性?(问题F) |
本篇将以Windows操作系统为例详细探讨操作系统对软件调试的支持。第8章介绍Windows操作系统的概况和关键概念,为理解后面章节的内容打基础。此后的内容可以分为5块。
第9章和第10章将着重讨论问题A,包括支持应用程序调试的用户态调试子系统,调试会话的建立过程及调试事件的产生和分发机制等。
与第2章的CPU异常相呼应,第11章和第12章将从操作系统的层面分析异常的分发和处理机制及系统处置未处理异常的方法。这一块内容的主题是异常处理,它与所有6个问题都相关。
第13~17章将把视线转向调试器之外的辅助调试机制(问题B、D和F)。第13章将分析Windows系统提供的错误提示机制。第14章会介绍Windows XP系统引入的错误报告机制(WER)。第15章会分析Windows的事件日志(Event Log)机制。第16章将分析Windows事件追踪机制(ETW)。
内核调试对于解决系统级的问题和学习操作系统有着非常重要的意义。因此,第18章我们将深入介绍Windows的内核调试引擎。
第19章将介绍用于提高测试和调试效率的验证机制(Verifier),包括应用程序验证和驱动程序验证。
|