Windows功能层次:
图1
Windows内核为用户模式代码提供一组系统服务,但应用程序通过一组系统dll最终通过ntdll.dll切换到内核模式下的执行体API函数中调用内核中的系统服务。Ntdll.dll是连接用户模式代码和内核模式系统服务的桥梁。对于内核提供的每一个系统服务,该DLL都提供一个相应的存根函数,这些存根函数名称以“Nt”作为前缀。Ntdll.dll还提供了许多系统级的支持函数,比如映像加载器函数(以“Ldr”为前缀)、Windows子系统进程通信函数(以“Csr”为前缀)、调试函数(以“Dbg”为前缀)、系统事件函数(以“Etw”为前缀),以及一般的运行支持函数(以“Rtl”为前缀)和字符串支持函数等。
32位系统中,2GB以下称为进程地址空间,2GB以上称为系统地址空间。实际上,两者之间有一块特殊的64KB地址空间,位于0x7fff0000~0x7ffffffff,两种模式下都不可访问。代码中的函数首先检查内存目标地址是否越过了此特殊区域,越过则访问违例;然后,试图将目标地址处的值赋给该地址,即触发一次该地址处的读和写操作,若该内存地址处当前线程不可写,则引发异常,从而使该代码片段中的except子句截获控制。Windows通过这种方式来捕获“用户模式代码传递一个系统空间地址”或者“传递一个无效内存地址”的情形。————那么,用户模式代码对2GB以上地址的访问将导致0x7fff0000~0x7fffffff间的内存访问错误?经过测试不是。实际过程应该是:导致异常后不再实际读/写地址,而是直接返回一个访问错误。
Windows的内核按照面向对象的思想设计,管理两种类型的对象:分发器对象和(dispatcher object)和控制对象。分发器对象实现了各种同步功能,这些对象的状态会影响线程的调度。Windows内核实现的分发器对象包括事件(event)、突变体(mutant)、信号量(semaphore)、进程(process)、线程(thread)、队列(queue)、门(gate)和定时器(timer)。控制对象用于控制内核的操作,但是不影响线程的调度,它包括异步过程调用(APC)、延迟过程调用(DPC)以及中断对象等。
Windows更高级的抽象:
图2
Windows中,内核代码可以访问当前进程的整个4GB虚拟地址空间,用户代码只能访问底端的2GB虚拟地址(或3GB,如果打开了内核启动开关/3GB)。
Windows子系统是一个支持用户应用程序的执行环境,除了Windows子系统作为原生环境子系统外,还支持POSIX和OS/2环境子系统。但自XP系统后,只有Windows子系统随系统一起发行。
可以将Windows内核分为三层:与硬件直接打交道的硬件抽象层(HAL),把所有和硬件相关联的代码逻辑隔离到一个专门模块中,从而使上面的层次尽可能做到独立与硬件平台;HAL之上的内核层包含了基本的操作系统原语和功能,如线程和进程、线程调度、中断和异常的处理、同步对象和各种同步机制。内核之上是执行体(executive)层,目的是提供一些可供上层应用程序或内核驱动程序直接调用的功能和语义。Windows内核的执行体包含一个对象管理器,用于一致地管理执行体中的对象。执行体层和内核层位于同一个二进制模块中,即内核基本模块,名为ntoskrnl.exe。
内核层和执行体层的分工是:内核层实现操作系统的基本机制,所有策略留给执行体。执行体中对象绝大多数封装了一个或多个内核对象,并通过某种方式(比如对象句柄)暴露给应用程序。这种设计体现了机制与策略分离的思想。——内核提供基本对象,执行体封装了对于内核中对象的操作,并将操作接口提供给编程者。
执行体是内核模块ntoskrnl.exe的上层部分,包含五种类型的函数:
·被导出的、可在用户模式下调用的函数。接口位于ntdll.dll模块中,应用程序可通过Windows API间接调用
·虽已被导出并可在用户模式下调用,但无法通过任何一个Windows API调用的函数。比如LPC(Local Procedure Call,本地过程调用)函数、各种查询函数(如NtQueryInformation<Xxx>),以及一些专用函数比如NtCreatePagingFile等。对这些函数的调用需要直接链接ntdll.dll——即,Windows API不提供对这些函数的调用接口,但是用户可以直接链接ntdll.dll调用
·只能在内核模式下调用的导出函数,并在Windows DDK(DDK是Device Development Kit,设备开发包)中有关于这些函数的文档。可被驱动程序调用——DDK有说明文档,但是也是间接通过ntdll.dll调用
·供执行体组件之间相互调用,但未被文档化的函数,包括执行体内部使用的一组支持函数
·属于一个组件的内部函数
执行体包括以下组件(对应图1):
1)进程和线程管理器,创建、终止等
2)内存管理器,实现了虚拟内存管理,既负责系统地址空间的内存管理,又为每个进程提供了一个私有的地址空间,并且也支持进程之间内存共享。内存管理器也为缓存管理器提供了底层支持
3)安全引用监视器(SRM, Security Reference Monitor)。强制在本地计算机上实施安全策略,守护操作系统的资源,执行对象的保护和审计
4)I/O管理器,实现与设备无关的输入和输出功能,负责将I/O请求分发给正确的设备驱动程序
5)缓存管理器,为文件系统提供了统一的数据混寸支持,允许文件系统驱动程序将磁盘中的数据映射到内存中并通过内存管理器来协调物理内存的分配
6)配置管理器,负责系统注册表的实现和管理
7)即插即用管理器,负责列举设备,为每个列举到的设备确定驱动程序并加载、初始化相应驱动程序。检测到系统中设备变化时,负责发送恰当的事件通知
8)电源管理器,负责协调电源事件,向设备驱动程序发送电源I/O通知。系统电源状态变化时,通知设备驱动程序处理设备的电源状态。即插即用设备的管理和电源的管理可看做是I/O管理器的扩展功能
还有四组主要支持函数,供以上执行体组建调用。有差不多1/3的支持函数可在Windows DDK中找到相应文档。这四类是:
·对象管理器,负责创建、管理、删除Windows执行体对象,以及用于表达操作系统资源的抽象数据类型,比如进程、线程和各种同步对象
·LPC设施。LPC设施负责同一台机器上的客户进程和服务器进程间传递消息。LPC是RPC(Remote Promote Call,远程过程调用,关于网络上客户进程和服务器进程之间通信的工业标准)的一个优化版本
·一组运行时库函数。功能广泛,涵盖字符串处理、算术运算、数据类型转换和安全结构处理等
·执行体支持例程。如系统内存分配(换页内存池和非换页内存池)、互斥的内存访问,以及对两种特殊类型同步对象(资源和互斥体)的支持