Windows 有这么多不同的版本,而每个版本又使用同样的内核映像,那么,系统如何知道引导了哪个发行版本呢?
只需查询注册表的 HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions
键下的 ProductType
和 ProductSuite
两个值。ProductType 可用来区分当前的系统是一个客户机系统还是服务器系统(什么样的服务器)。
系统根据前面所述的许可策略文件将这些值加载到注册表中。它的有效取值如表 2.3 所示。
在用户模式下可通过 GetVersionEx 函数查询到此值,在设备驱动程序中使用内核模式支持函数 RtGetVersion 也可以查询到此值。
另一个注册表值,ProductPolicy,包含了 tokens. dat 文件中数据的一份缓存副本,它随 Windows 版本的不同而不同,而且也随系统支持的特性的不同而不同。
如果用户程序需要判断当前运行的是哪个版本的 Windows.系统,可以调用 Windows 的 VerifyVersionlnfo 函数。Windows SDK 中有关于该函数的文档。设备驱动程序可以调用内核模式函数 RtVerify Versionlnfo。WDK 中有关于此函数的文档。
既然系统的核心文件在客户机版本
和服务器版本
中本质上是相同的,那么,系统在运行过程中又是如何有所不同呢
?
简而言之,在默认配置下,服务器系统针对系统吞吐量做了优化,使之成为高性能应用服务器:而客户机版本呢,虽然它也有服务器的能力,但是它针对交互式桌面用途下的响应时间做了优化。例如,在系统引导时,根据产品类型的不同,有几项资源分配的决策是不同的,比如操作系统堆 (heap) 或者内存池 (pool) 的大小和数量、内部的系统辅助线程 (system worker thread) 的数量,以及系统数据缓存的大小。而且,运行时的策略决策,比如内存管理器用何种方式来平衡系统和进程的内存需求,在服务器版本和客户机版本中也是不同的。甚至线程调度中的有些细节在这两大产品族中也有不同的默认行为,比如时间片或者线程时限 (quantum,详见第 5 章) 的默认长度。
凡是在两大产品族中有重要运行差异的地方,在本书接下来的有关章节中都会加以强调。除非另有说明,否则,本书中介绍的内容可同时适用于客户机版本和服务器版本。
实验:通过许可策略支持的特性
检查版本
Windows有一个特殊的调试版本,称为检查版本(checked build)(只有MSDN的操作系统订阅用户才可以获得)。这是Windows源代码在定义了“DBG”标志后重新编译得到的一个版本,因而用于调试和跟踪的编译时条件代码也被包含了进来。
而且,为了机器代码更加易于理解,针对Windows二进制代码的后处理优化(为了执行得更快而进行的代码布局结构优化)并没有被执行(参见Windowsi调试工具帮助文件中的“Debugging Performance-Optimized Code”部分)。
之所以提供这样的检查版本,主要是为了帮助设备驱动程序开发人员,因为它可以针对那些被设备驱动程序或其他系统代码所调用的内核模式函数执行更为严格的错误检查。例如,如果驱动程序(或者其他的内核模式代码)对系统函数执行了一次无效调用(比如,在错误的中断级别上获取自旋锁),并且该系统函数会检查传递进来的参数,那么,当检测到问题以后系统就会停止执行,而不是允许某些数据结构被破坏,使系统可能在稍后的某个点上再崩溃。
实验:确认是否正在运行Windows的检查版本
在检查版本的二进制代码中,大多数附加的代码都是使用了ASSERT宏和/或NT_ASSERT宏之后的结果,这两个宏定义在WDK头文件Wdm.h中,WDK文档中有关于两者的介绍。这些宏测试一个条件(比如一个数据结构或者参数的有效性),如果表达式的计算结果是FALSE,那么这两个宏调用内核模式函数RtlAssert,该函数又进一步调用DbgPrintEx,将调试消息的文本发送到一个调试消息缓冲区中。如果有一个内核调试器被附载到当前系统中,则该消息被显示出来,并自动跟上一个提示,请用户来决定该如何处理这一断言失败(断点、忽略、终止进程,或者终止线程)。如果当前系统不是与内核调试器一起引导起来的(在引导配置数据库,即BCD中使用了debug选项),并且也没有附载内核调试器,那么,ASSERT测试的失败将会导致系统进入错误检查(bugcheck)。关于某些内核支持例程所执行的各种ASSERT检查,参见WDK文档中的“Checked Build ASSERTS”部分。
检查版本对于系统管理员也是非常有用的,因为他们可以针对特定的组件跟踪到进一步的细节(有关详细指令, 参见Microsoft知识库中编号为314743的文章, 题目为HOWTO:
Enable Verbose Debug Tracing in Various Drivers and Subsystems) 。这些信息被通过前面提到的函数, Dbg Print Ex, 发送到一个内部的调试消息缓冲区。要查看这些调试消息, 你或者将一个内核调试器附载到目标系统上(这要求在调试模式下引导目标系统),并且在执行本地内核调试时使用!dbg print命令; 或者使用Sysinternals出品的Dbg view.exe工具(www.microsofi.com/technet/sysinternals)。
要发挥操作系统调试版本的优势,不必安装整个检查版本。可以只复制内核映像(N to skr nl.exe) 和正确的HAL(Hal.dll) 的检查版本到一个普通的零售版本系统中。这种做法的好处是,设备驱动程序和其他的内核代码受到了检查版本的严格检查,但是又不必运行系统中其他所有组件的较慢的调试版本。如何做到这一点呢?详细的指令参见WDK文档中的“Installing Just the Checked OperatingSystem and HAL”部分。
最后,检查版本对于测试用户模式代码也是非常有用的,因为系统的时序会发生变化。
(这是因为,附加的检查只是在内核中进行的,并且内核的组件都是未经编译优化的。)通常,多线程同步错误往往跟特定的时序条件有关。如果在检查版本的系统上(或者至少内核和HAL 是检查版本的)运行测试程序,那么由于整个系统的时序是不同的,将有可能使那些在普通的零售系统中不会发生的潜在时序错误暴露出来。
系统软件层面组成
- 注册表
- 事件日志
- 本地组和本地安全策略
2.4 关键系统组件
Windows系统架构
环境子系统和子系统DLL
环境子系统的角色是,将基本的Windows执行体系统服务的某个子集暴露给应用程序
。
每个子系统都提供了对于Windows原生服务的一个不同子集的访问能力。这意味着,建立在某个子系统上的应用程序可以做到的事情,可能是另一个建立在不同子系统上的应用所无法做到的。例如,Windows应用程序不能够使用SUA的fork函数。
每个可执行映像(.exe)都被绑定到一个(且唯一的)子系统上。映像文件运行时,负责创建进程的代码会检查该映像头部的子系统类型代码,所以它可以通知正确的子系统,有新的进程被创建。在Microsoft Visual C++中,link命令的/SUBSYSTEM修饰符可以指定此类型代码。
正如前面所讲,用户应用程序并不直接调用Windows的系统服务,而是通过一个或者多个子系统DLL来进行。这些库导出的接口都有很好的文档说明,凡是链接到该子系统的程序都可以调用这些接口。例如,Windows子系统DLL(比如Kernel32.dll、
Advapi32.dll、User32.dll 和Gdi32.dll)实现了WindowsAPI函数。SUA子系统DLL(Psxdll.dll)实现了SUAAPI函数。
实验:查看可执行影响的子系统类型
当应用程序调用子系统DLL中的某个函数时,可能会发生下述三件事情之一:
- 该函数完全是在该子系统DLL中实现的,在用户模式下运行。换句话说,该函数并没有给环境子系统进程发送消息,也没有调用Windows执行体系统服务。该函数是在用户模式下完成的,运行的结果被返回给调用者。此类函数的例子有GetCurrentProcess (它总是返回-1,在所有与进程相关的函数中,-1被定义为代表当前进程)和GetCurrentProcessld (对于一个正在运行的进程,进程ID不会改变,所以此进程ID可以从某个缓存的地方获取到,从而避免要调用至内核中)。
- 该函数要求调用Windows执行体一次或者多次。例如, Windows的ReadFile和WriteFile 函数分别要调用底层内部的(且无文档的) Windows 1/O系统服务NtReadFile和NtWriteFile。
- 该函数要求在环境子系统进程中完成某些工作(环境子系统进程运行在用户模式下,负责维护那些在其控制下运行的客户应用程序的状态)。在这种情况下,该函数通过消息的形式向环境子系统发送客户机/服务器请求,从而让子系统执行某个操作。然后子系统DLL等待应答,收到应答之后再返回调用者。
有些函数可以是以上列出的第2和第3项的组合, 比如Windows的CreateProcess和CreateThread函数。
子系统启动
子系统是由会话管理器(Session Manager)(Smss.exe)进程启动起来的,子系统的启动信息保存在注册表键
HKLMISYSTEM\CurrentControlSet\Control\Session Manager\Subsystems
的下面。
Required值列出了系统引导时加载的子系统。
该值有两个字符串:
- Windows
- Debug。
Windows值包含了Windows子系统的文件规范,Csrss.exe,它代表了客户机/服务器运行时子系统(Client/Server Run-Time Subsystem)。
Debug值是空的(因为它被用于内部测试),因此什么也不是。Optional值表明了SUA子系统将会按需启动。注册表值Kmode包含了Windows子系统的内核模式部分的文件名称,Win32k.sys(本章后面将进一步解释)。
Windows子系统
尽管Windows在设计时, 要求支持多个独立的环境子系统, 但是从实践的角度来看, 让每个子系统都实现所有的代码来处理窗口和显示I/O,显然会导致大量重复的系统函数,无论是对系统的体积, 还是对系统的性能, 最终必然带来负面影响。因为Windows是基础的子系统,所以Windows的设计者决定将这些基本的功能放在Windows子系统中, 让其他的子系统调用Windows子系统来完成显示I/O。因此, SUA子系统调用Windows子系统中的服务来完成显示I/O。
这种设计决策的一个结果是, 对于任何Windows系统, Windows子系统总是一个必需的组件, 即使在一个没有交互用户登录的服务器系统上也是如此。由于这一原因, Windows子系统进程被标记为关键进程(意味着一旦它出于某种原因退出,系统就会崩溃)。
Windows子系统由以下主要的组件构成:
- 对于每个会话,环境子系统进程(Csrss.exe)有一个实例加载三个DLL(Basesrv.dll、Winsrv.dll和Csrsrv.dll),它们包含下列支持:
– 创建或删除进程和线程。
– 对16位DOS虚拟机(VDM)进程的部分支持(仅32位Windows)。sxs (Side-by-side)/Fusion和清单文件(manifest)支持。
– 其他一些函数,比如GetTempFile、DefineDosDevice、ExitWindowsEx,以及几个自然语言支持函数。 - 内核模式设备驱动程序( Win32k.sys)包含下列支持:
– 窗口管理器( window manager),它控制窗口显示,管理屏幕输出,采集来自键盘、鼠标和其他设备的输入,同时也负责将用户消息传递给应用程序。
– 图形设备接口(GDI,Graphics Device Interface),它是专门针对图形输出设备的函数库,其中包括线段、文本和图形的绘制函数,以及图形控制函数。
– DirectX功能的包装函数,Windows对DirectX的支持是在另一个内核驱动程序( Dxgkrnl.sys)中实现的。 - 控制台宿主进程(Conhost.exe),提供了对控制台(字符环境〉应用程序的支持。
- 子系统DLL (比如Kernel32.dll、Advapi32.dll、User32.dll和Gdi32.dll),将已经文档化的Windows API函数,转译成Ntoskrnl.exe和Win32k.sys中恰当的且绝大多数未文档化的内核模式系统服务调用。
- 图形设备驱动程序,与硬件相关的图形显示器驱动程序、打印机驱动程序和视频微端口驱动程序。
应用程序调用标准的USER函数在显示器上创建用户界面控件,比如窗口和按钮。窗口管理器将这些请求发送给GDI,而GDI又将它们传递给图形设备驱动程序;在设备驱动程序内部,这些请求被格式化以适合特定的显示器设备。显示器驱动程序与视频微端口驱动程序是成对的,用以实现对视频显示的支持。
GDI提供了一组标准的二维函数,使得应用程序无须知道任何有关图形设备的信息就可以与设备进行通信。GDI函数位于应用程序和图形设备(比如显示器驱动程序和打印机驱动程序)的中间。GDI负责解释应用程序的图形输出请求,并且将这些请求发送给图形显示器驱动程序。它也为应用程序提供了一个标准的接口,以便这些应用程序可以使用各种不同的图形输出设备。正是有了这一接口,使得应用程序代码可以独立于硬件设备和它们的驱动程序。
GDI对它的消息进行剪裁,以符合设备的能力,它通常要将应用程序的请求分解成多个易于处理的部分。例如,有些设备可以理解画椭圆的命令,而其他的设备则要求GDI将该命令解释成“将一系列像素放置在特定的坐标处”。有关图形和视频驱动程序架构的更多信息,请参考WDK中"Display (Adapters and Monitors)”一章的“Design Guide”一节。
因为子系统的大部分(尤其是显示I/O的功能部分)运行在内核模式下,所以,只有少数一些Windows函数要向Windows子系统进程发送消息:进程和线程的创建和终止、网络驱动器号,以及临时文件的创建。一般而言,一个正在运行的Windows应用程序不会引起很多(如果有的话)至Windows子系统进程的环境切换。
控制台窗口宿主进程
在最初的Windows子系统设计中,子系统进程(Csrss.exe)负责管理控制台窗口,每个控制台应用程序(比如Cmd.exe,“命令提示符”程序)与Csrss进行通信。现在,Windows为系统中的每个控制台窗口使用了一个单独的进程:控制台窗口宿主进程(Conhost.exe)。(多个控制台应用程序可以共享同一个控制台窗口,比如在从命令提示符窗口中发起一个新的命令提示符窗口时。默认情况下,第二个命令提示符窗口共享前者的控制台窗口。)
无论何时,只要控制台应用程序向当前会话中正在运行的Csss实例注册其自身,Csss就利用客户进程的安全令牌,而不是Csrss的System令牌来创建Conhost:实例。然后,它映射一个共享内存区,让所有的Conhosti都可以与Csrss共享一部分内存,以便于高效地处理缓冲区(因为这些线程不再运行在Csrss内部了),并且Csrss也在RPC Control对象目录中创建一个命名的异步本地过程调用(ALPC,Asynchronous Local Procedure Call)端口。(有关ALPC的更多信息,参见第3章。)该端口的名称采用console-PID-lpc-handle的格式,其中PID是Conhost进程的进程ID。然后,它向用户应用程序所关联的内核进程结构注册它的PID,因而用户应用程序可以查询此信息,以便打开新创建的ALPC端口。该进程也会创建一个共享内存区对象的映射关系,从而在命令行应用程序和它的Conhost之间可以共享数据。最后,在会话0的BaseNamedObjects目录中创建一个等待事件(名为ConsoleEvent-PID),从而使命令行应用程序和Conhost可以相互之间通知新的缓冲区数据。下面的图显示了一个Conhosti进程有两个句柄已经打开了此ALPC端口和等待事件。
因为Conhost是用用户的凭证来运行的(意味着用户的特权级别),并且也运行在一个与控制台应用程序相关联的进程中,所以,用户界面特权隔离(UIPI,User Interface Privilege Isolation参见第6章“安全性”)安全机制也适用于控制台进程。而且,CPU制约的控制台应用程序可能会被识别为它们背后的控制台宿主进程(若有必要,用户可以杀掉它)。另外还有一种副作用,因为Conhost进程现在运行在Csrss子系统的特别辖区以外,所以,控制台应用程序(它们的窗口实际上属于Conhost)可以完全主题化,可以加载第三方DLL,还可以拥有完全的窗口能力。
UNIX应用子系统
针对UNIX应用程序的子系统(SUA,Subsystem for UNIX-based Application)使得可以在一台运行Windows Server系统,或者Windows客户机系统的企业或旗舰版本的计算机上编译和运行UNIX应用程序。SUA提供了将近2000个UNX函数和300个UNIX类的工具和实用程序。
(有关SUA的更多信息,参见 )
有关Windows如何处理POSIX应用程序运行的更多信息,参见第5章“CreateProcess的流程”一节。
最初的POSIX子系统
POSIX差不多可以看成“a Portable Operating System Interface based on UNIX(一个基于UNX的可移植的操作系统接口
)”的缩写,它指的是针对UNX风格的操作系统接口的一组国际标准。
POSX标准鼓励厂商实现UNX风格的接口,从而使它们保持兼容,这样程序员们就可以很容易地将他们的应用程序从一个系统迁移到另一个系统上。Windows最初仅仅实现了众多POSIX标准中的一个,即POSIX.1,正式的名称是ISO/IEC 9945-1:1990或者IEEE POSIX标准1003.1-1990.该标准之所以被包含进来,主要是为了满足美国政府在20世纪80年代中后期制定的政府采购要求,即POSX.1兼容性是强制性的,这是在美国标准和技术委员会(National Institute of Standards and Technology)开发的FIPS(Federal Information Processing Standard,联邦信息处理标准)l5l-2中规定的。Windows NT3.5、3.51和4已经被正式测试过,并且通过了FPS151-2的鉴定。
因为POSX.l兼容性是Windows的一个强制性目标,所以,在设计Windows操作系统时,必须要保证所设计的基本系统能够支持POSX.1子系统一一比如fork函数是在Windows执行体中实现的,而针对文件硬链接(hard file link)的支持则在Windows文件系统中。
Ntdll.dll
Ntdll.dll是一个特殊的系统支持库,主要用于子系统DLL。它包含两种类型的函数:
- 系统服务分发存根(stub),它们会调用Windows执行体的系统服务。
- 内部支持函数,供子系统、子系统DLL以及其他的原生映像文件使用。
第一组函数为Windows执行体系统服务提供了接口,在用户模式下可以通过这些接口函数调用Windows执行体的系统服务。这样的函数超过了400个,比如NtCreateFile、NtSetEvent等。
如前所述,这些函数的大多数功能可以通过Windows API来访问得到(然而,有些函数则不然,它们仅被用于操作系统内部)。
对于每一个这样的函数,Ntl包含了一个同名的入口点。函数内部的代码包含了与处理器体系架构相关的模式切换指令,通过该指令可转换到内核模式下,从而调用系统服务分发器(system service dispatcher,第3章将详细介绍)。系统服务分发器在检验某些参数以后,再调用真正的内核模式系统服务,其中包括Ntoskrnl.exe内部的实际代码。
对于每一个这样的函数,Ntdll包含了一个同名的入口点。函数内部的代码包含了与处理器体系架构相关的模式切换指令,通过该指令可转换到内核模式下,从而调用系统服务分发器(system service dispatcher,第3章将详细介绍)。系统服务分发器在检验某些参数以后,再调用真正的内核模式系统服务,其中包括Ntoskrnl.exe内部的实际代码。
Ntdll也包含许多支持函数,比如:
- 映像加载器(以Ldr开头的函数)、
- 堆管理器、
- Windows子系统进程通信函数(以Cs开头的函数)。
Ntdll也包含一般性的运行库例程(以Rtl开头的函数)、对用户模式调试和Windows事件跟踪的支持函数(分别以DbgUi和Ew开头的函数),以及用户模式异步过程调用(APC,Asynchronous Procedure Call)分发器和异常分发器(关于APC和异常,将在第3章中讲述)。最后,你还可以在Nt中发现一个很小的C运行库(CRT)例程的子集,仅限于字符串和标准库中的一些例程,比如nemcpy、strcpy、itoa,等等。
执行体
Windows执行体是Ntoskrnl…exe中的上层(内核是其下层)。执行体包含以下类型的函数:
- 可在用户模式下调用的导出函数。这些函数称为系统服务(system service),并且通过Ntdl被导出。这些服务绝大多数可通过Windows API来访问,或者通过另一个环境子系统的API来访问。然而对于有些服务,通过任何一个文档化的子系统函数都无法访问(这样的例子有ALPC、诸如NtQueryInformationProcess之类的各种查询函数,以及诸如NtCreatePagingFilei这样的专用函数,等等)。
- 可通过DeviceloControli函数来调用的设备驱动程序函数。这为从用户模式到内核模式提供了一个通用的接口,因而在用户模式下可以调用设备驱动程序中并不与读或者写操作关联的函数。
- 只能在内核模式下调用的导出函数,这些函数在WDK中已经文档化。
- 在内核模式下调用,但未在WDK中文档化的导出函数(比如以Inbv开头的、在引导视频驱动程序中调用的函数)。
- 定义为全局符号但是未被导出的函数。这包括在Ntoskrnl内部调用的支持函数,比如以Iop或者M开头的那些函数(分别是I/O管理器内部支持函数和内存管理内部支持函数)。
- 未定义为全局符号,而是在一个模块内部的函数。
执行体包含了以下的主要组件(在本书后续章节中会详细地介绍):
配置管理器(configuration manager,在第4章中介绍)
负责实现和管理系统的注册表。进程管理器(process manager,在第5章中介绍)
创建和终止进程和线程。针对进程和线程的底层支持是在Windows内核中实现的;而执行体则在这些低层对象的基础上又加上了额外的语义和功能。安全引用监视器(security reference manager,SRM,在第6章中讲述)
强制在本地计算机上实行安全策略。它守护着操作系统的资源,执行对运行时对象的保护和审计。I/O管理器(I/O manager,在本书下册第8章中解释)
实现了与设备无关的/O功能,负责将/O请求分派到恰当的设备驱动程序以进一步处理。即插即用(PnP)管理器(Plug and Play manager,在本书下册第8章中解释)
的任务是,为了支持某个特定的设备,确定哪些驱动程序是必需的,同时也负责加载这些驱动程序。它在设备枚举过程中,获取到每个设备的硬件资源需求。PP管理器根据每个设备的资源需求,分配适当的硬件资源,比如I/O端口、RQ、DMA通道和内存位置。当系统中的设备变化(增加或者移除设备)时,它还负责发送恰当的事件通知。电源管理器(power manager,在本书下册第8章中解释)
负责协调电源事件,并且产生电源管理/O通知,发送给设备驱动程序。电源管理器可以配置成:当系统空闲时,通过将CPU置于睡眠状态而降低电源消耗。单个设备的电源消耗变化可由设备驱动程序来处理,但是需要电源管理器来协调。Windows驱动程序模型(Windows Driver Model)
的WMI例程(在第4章中解释)允许设备驱动程序发布有关性能和配置的信息,以及接收来自用户模式WMI服务的命令。WMI信息的消费者可以运行在本地机器上,也可以在跨网络的远程机器上。缓存管理器(cache manager,在本书下册第1l章中解释)
提高了基于文件的I/O操作的性能,其做法是,让最近引用过的磁盘数据驻留在主内存中以便快速访问(并且延迟磁盘写操作,在将更新数据发送到磁盘之前先在内存中停留一小段时间)。你将会看到,它利用了内存管理器对映射文件的支持来做到这一点。内存管理器(memory manager,,在本书下册第10章中解释)
实现了虚拟内存。这是一种内存管理方案,它为每个进程提供一个巨大的私有地址空间,其大小可以超过当前可用的物理内存。内存管理器也为缓存管理器提供相应的底层支持。逻辑预取器(logical prefetcher)和Superfetch(在本书下册第l0章中解释)
用于加速系统和进程的启动过程。其做法是,对于要在系统或进程启动过程中引用的数据,它优化这些数据的加载过程。
另外,Windows执行体还包含四组主要的支持函数,以上这些执行体组件会用到这些支持函数。在这些支持函数中,差不多三分之一在WDK中有相应的文档,因为设备驱动程序也要用到它们。以下就是这四大类支持函数:
对象管理器(object manager)
,创建、管理和删除Windows执行体对象和抽象数据类型,它们代表了操作系统的资源,比如进程、线程和各种同步对象。第3章将介绍对象管理器。高级LPC设施(ALPC facility,在第3章中解释)
,为同一台机器上的客户机进程和服务器进程传递消息。此外,ALPC也被用作RPC的一个本地传输实现,这里的RPC是指跨网络的客户机进程和服务器进程之间的工业标准通信设施。一组涉及范围广泛的公共运行库函数
,比如字符串处理、算术操作、数据类型转换,以及安全结构处理等。执行体支持例程
,比如系统内存分配(换页的和非换页的内存池)、互锁的内存访问,以及三种特殊类型的同步对象:资源、快速互斥体(fast mutex)和推锁(pushlock)。
执行体还包含了其他多种基础设施例程,在本书后面我们将只是简单地提及其中一部分:
内核调试器库(kernel debugger library)
使得内核的调试与支持KD的调试器保持独立,这里KD是指一个可移植的协议,可以承载在各种传输体(比如USB和EEE1394)上。WinDbg和Kd.exe工具实现了KD协议。用户模式调试框架(user-mode debugging framework)
负责向用户模式调试API发送事件,支持断点和单步跟踪代码,以及改变运行线程的执行环境。内核事务管理器(kernel transaction manager)
提供公共的两阶段提交机制供资源管理器(resource manager)。使用,比如事务型注册表(TxR,transactional registry)和事务型NTFS(TxF,transactional NTFS)。超级管理器库(hypervisor library)
是Windows Server2008中Hyper-V栈的一部分,它提供了虚拟机环境的内核支持。当系统知道它在一个客户区(虚拟环境)中运行时,超级管理器库可以优化相应的内核代码。错误修正管理器(errata manager)
为非标准的或非兼容的硬件设备提供绕行的解决方案。驱动程序检验器(Driver Verifier)
为内核模式驱动程序和代码提供可选的一致性检查机制。Windows事件跟踪(Event Tracing for Windows)
为内核模式和用户模式组件提供了许多用于在系统范围内进行事件跟踪的辅助例程。Windows诊断设施(Windows diagnostic infrastructure)
,对基于诊断场景(diagnostic scenario)的系统活动进行智能跟踪。Windows硬件错误体系架构(Windows hardware error infrastructure)
支持例程提供了一个用于报告硬件错误的公共框架。文件系统运行库(file-system runtime library)
为文件系统驱动程序提供了一组公共的支持例程。