(一)需求和设计目标

     Windows NT设计小组在项目开始之初选择了下面的设计目标:

(1)扩展性:编写的系统代码必须能够随着市场需求的变化而自如增长和改变。

(2)可移植性:系统必须能运行在多种硬件体系架构上,必须能根据市场的需要,相对容易地迁移到新的体系架构上。

(3)可靠性和健壮性:系统应该能够保护自己,不会因内部的故障和外部的篡改而不能工作。应用程序应该无法伤害操作系统或其他应用程序。

(4)兼容性:虽然Windows NT应该扩展已有的技术,但是它的用户界面和API应该与老版本的WindowsMS-DOS兼容。而且它也应该能与其他的系统很好的互操作。

(5)性能:在其他设计目标的约束下,系统在每一种硬件平台上应尽可能运行得更快,对外部的响应尽可能地及时。


(二)操作系统模型

Windows操作系统的大部分代码与设备驱动程序代码共享同样的受保护的内核模式内存空间。Windows内核的保护机制有助于减缓或避免与“共享内核模式地址空间”有关的问题发生。操作系统的所有组件都是完全受保护的不会被错误的应用程序破坏,因为应用程序不能直接访问操作系统中特权部分的代码和数据。Windows无论是作为应用服务器,还是工作站平台,从操作系统核心服务的角度来看,它的健壮性与稳定性良好,之所以如此,对操作系统组件的这种保护是原因之一。

Windows的内核模式组件体现了基本的面向对象设计原则。虽然Windows内部普遍使用了对象来表达共享的系统资源,但是,从严格意义上讲,Windows并不是一个面向对象的系统。出于移植性的考虑,Windows操作系统的大多数代码是用C语言编写的。C语言并不直接支持向对象的语法元素。因此,Windows 中基于C语言的对象实现只是借用了(但并不依赖于)特定的面向对象语言的特性。


(三)总体架构

wKioL1WKtPmjeYDIAADblneGDZ8370.jpg

上图中,首先可注意到中间有一条线把Windows操作系统的用户模式和内核模式两部分划开来。线上面的方框代表了用户模式的进程,线下面的组件是内核模式的操作系统服务。用户模式的线程在一个受保护的进程地址空间中执行。因此,系统支持进程、服务进程、用户应用程序和环境子系统都有它们各自的私有进程地址空间。

    用户模式进程有如下四种基本类型:

(1)固定的(或者硬性指定的)系统支持进程system support process),比如登录(logon)进程和会话管理器(session manager),它并不是Windows服务。

(2)服务进程(service process)宿纳的是Windows服务Windows服务往往要求独立于用户登录而运行。许多Windows服务器应用也包含了一些以Windows服务方式来运行的组件。

(3)用户应用程序User application),可以是下面几种类型之一:Windows32位或64位,Windows 3.1 16位,MS-DOS 16位或者POSIX 32位或64位。注意,16位应用程序只能运行在32Windows上。

(4)环境子系统服务器进程environment subsystem server process)实现了操作系统环境(environment)的支持部分。这里所谓的环境是操作系统展示给用户或者程序员的个性化的部分。

Windows下,用户应用程序并不直接调用原生的Windows操作系统服务,而是通过一个或者多个子系统动态链接库(DLL)来发起调用。子系统DLL的角色是,将一个已文档化的函数转化为一些恰当的内部原生系统服务调用。这一转化过程可能会--也可能不会--向正在为用户应用程序提供服务的环境子系统进程发送消息。

     Windows的内核模式组件包含:

(1)Windows执行体包含了基本的操作系统服务,比如内存管理、进程和线程管理、安全性、I/O、网络和跨进程通信。

(2)Windows内核是由一组低层次的操作系统功能构成的,比如线程调度、中断和异常分发,以及多处理器同步。它也提供了一组例程和基本对象,执行体的其余部分利用这些例程和对象实现更高层次的功能。

(3)设备驱动程序(device driver)既包括硬件设备驱动程序,也包括像文件系统和网络驱动程序之类的非硬件设备驱动程序。其中硬件设备驱动程序将用户的I/O函数调用转换成特定的硬件设备I/O请求。

(4)硬件抽象层(HALHardware Abstraction Layer)是指一层特殊的代码,它把内核、设备驱动程序和Windows执行的其余部分,跟与平台相关的硬件差异隔离开来。

(5)窗口和图形系统(windowing and graphic system)实现了图形用户界面(GUI)功能(更为人们熟知的叫法是Windows USERGDI两部分功能),比如对窗口的处理、用户界面控件,以及绘制等。


Windows的核心系统文件

文件名称

组件

Ntoskrnl.exe

执行体和内核

Ntkrnlpa.exe(仅用于32位系统)

执行体和内核,支持物理地址扩展(PAE),使得32位系统可寻址多达64GB物理内存,以及将内存标记为不可执行的

hal.dll

硬件抽象层

Win32k.sys

Windows子系统的内核模式部分

Ntdll.dll

内部支持函数,以及执行体函数的系统服务分发存根

Kernel32.dll,Advapi32.dllUser32.dlGdi32.dll

Windows的核心子系统DLL


(四)可移植性

Windows在设计时,就确定能够运行在各种不同的硬件体系架构之上。

Windows主要通过以下两种方法来实现可移植性,以支持多种硬件体系架构和平台:

Windows有一个分层设计,系统的低层部分是与处理器体系架构相关的,或者是与平台相关的,它们被隔离到独立的模块中,所以,系统的高层部分可以不考虑体系架构之间的差别,也不用关心硬件平台的差异。有两个关键的组件为操作系统提供了可移植性,它们是内核(包含Ntoskrnl.exe)和硬件抽象层(或称HAL,包含Hal.dll中)与体系结构相关的功能,比如线程环境切换(thread context switching)和陷阱分发(trap dispatching)是在内核中实现的。在同样的体系架构下,不同的系统之间有所差异的功能则是在HAL中实现的。另外还有唯一一个组件也有相当数量的代码是与体系架构相关的,那就是内存管理器,但是与整个系统相比,这仍然只是一小部分而已。

Windows的绝大部分代码是用C语言编写的,少部分是用C++编写的。只有那些需要直接与系统硬件打交道的部分,或者对性能极端敏感的操作系统部分,才是用汇编语言编写的。汇编语言代码不仅出现在内核和HAL中,也出现在操作系统核心的其他一些地方,还出现在Windows子系统的内核模式部分,甚至在某些用户模式库中,比如Ntdll.dll中的进程启动代码。


(五)对称多处理器

多任务(multitasking)是指让多个执行线程共享同一个处理器的操作系统技术。然而,当一台计算机有不止一个处理器时,它可以同时执行多个线程。因此,虽然一个多任务操作系统只不过看起来好像同一时刻可以执行多个线程,但是,一个多处理器操作系统可以真正地做到同一时刻执行多个线程,在每个处理器上执行一个线程。

Windows的一个关键设计目标是,必须能够很好地在多处理器计算机系统上运行。Windows是一个对称多处理器(SMPsysmetric multiprocessing)操作系统。没有主处理器--操作系统和用户线程可以被调度到任何处理器上运行。而且,所有的处理器共享唯一的内存空间。这种模型与非对称多处理器(ASMPasymemetric multiprocessing)不同,在一个典型的非对称多处理器操作系统中,系统选择其中一个处理器来执行操作系统内核代码,而其他的处理器只运行用户代码。如图所示:

Windows也支持三种现代的多处理器系统:多核、超线程和NUMA(非一致的内存架构)

超线程(Hyper-Threading)Intel引入的一项技术,它可以在每个物理核上提供多个逻辑处理器。每个逻辑CPU有自己的CPU状态,但是执行引擎和片上缓存则是共享的。这使得一个逻辑CPU可以在其他逻辑CPU停转的时候继续执行。调度算法已经被改进过了,因而可以最佳地利用支持超线程的机器,将线程调度到一个空闲的物理处理器上,现在则改进为“选择一个物理处理器上的空闲逻辑处理器(该处理器的其他逻辑处理器可能正忙着)”。

NUMA系统中,处理器被组织成更小的单元,称为节点(node)。每个节点有它自己的处理器和内存,并且通过一个缓存一致的互连总线连接到更大的系统上。NUMA系统上的Windows仍然作为一个SMP系统来运行,其中所有的处理器可以访问所有的内存--只不过,节点本地的内存访问起来比其他节点的内存更快一些而已。系统提高性能的做法是,根据线程用到的内存所在的节点,将线程调度到同一节点中的处理器上。系统尽可能地在节点内部满足内存申请的要求,只有在必要的时候才从其他的节点分配内存。

很自然,Windows也支持多核系统--因为这些系统有多个真正的物理核(只是在同一个芯片上)Windows中原来的SMP代码将这些核看作单独的处理器,但是,一些特定的需要记录和标识核的任务例外,这些任务需要区分是同一个处理器的核,还是不同插槽上的核。

Windows最初设计的时候并没有特定的处理器个数限制,只是不同的许可策略使Windows的不同发行版本有了差异。Windows用一个位掩码(有时候称为亲和性掩码(affinity mask))来记录和跟踪处理器(总数、空闲、忙,或诸如此类的细节),这里的位数与机器的原生数据类型(32位或64)相同,因而使得处理器可以直接在一个寄存器里操纵这些位。由于这个原因,Windows系统最初限定了CPU的个数在一个原生字的范围内,因为亲和性掩码不可能任意增长。为了保持兼容性,以及支持具有更多处理器的系统,Windows实现了一个更高级的概念,称为处理器组(processor group)。处理器组是指可以由一个亲和性掩码来定义的一组处理器,内核和应用程序在更改亲和性设置的过程中可以选择它们将使用哪一组。应用程序为保持兼容,可以查询当前系统支持多少组(目前限制4组),然后枚举出每个组的位掩码。同时,老的遗留下来的应用程序继续工作,它们只会看到它们当前所在的组。


(六)可伸缩性

多处理器系统的一个关键问题是可伸缩性。Windows内核的可伸缩性一直在不断进步。Windows集下面几个特性于一身,这些特性对于Windows作为一个多处理器系统的成功起到了至关重要的作用:

(1)能够在任何可用处理器上运行操作系统代码,也可以同时在多个处理器上运行系统代码。

(2)在单个进程内执行多个线程,每个线程可以在不同的处理器上并行地执行。

(3)内核内部的细粒度同步,以及在设备驱动程序和服务器进程内部的细粒度同步,这使得更多的组件可以在多个处理器上并发地运行。

(4)诸如I/O完成端口之类的编程机制,使得可以实现高效的多线程服务器进程,并且这样的进程在多处理器系统上有很好的可伸缩性。


(七)客户机和服务器版本之间的差异

Windows既发行客户机版本,也发行服务器版本的零售软件包。Windows76个客户机版本。Windows Server 2008 R27个不同版本。此外,客户机版本还有一种“N”版本。Windows Server 2008 R2还有相应的“Hyper-V”版本。这些版本在以下方面有所不同:

(1)所支持的处理器的数目(指的是插槽,不是核或线程);

(2)所支持的物理内存的数量(实际是指最高可用的RAM物理地址);

(3)所支持的并行网络连接的数量;

(4)支持媒体中心;

(5)支持多点触摸、Aero和桌面合成;

(6)对于诸如BitLockerVHD引导、AppLockerWindows XP兼容模式等特性的支持,另外还有100多个可配置的许可策略值;

(7)Windows Server版本附带的分层的服务,并不包含在客户机版本中。

虽然Windows操作系统有多个客户机和服务器零售软件包,但是它们共享同一组核心系统文件,包括内核映像Ntoskrnl.exeHAL库、设备驱动程序,以及基本的系统辅助工具和DLL。这些文件对于Windows 7Windows Server 2008 R2的所有发行版本都是相同的。只需查询注册表的HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions键下的ProductTypeProductSuite两个值。

ProductType的注册表值

Windows版本

ProductType的值

Windows客户机

WinNT

Windows服务器(域控制器)

LanmanNT

Windows服务器(仅服务器)

ServerNT

另一个注册表值,ProductPolicy,包含tokens.dat文件中数据的一份缓存副本,它随Windows版本的不同而不同,而且也随系统支持的特性的不同而不同。如果用户程序需要判断当前运行的是哪个版本的Windows系统,可以调用WindowsVerifyVersionInfo函数。设备驱动程序可以调用内核模式函数RtVerifyVersionInfo

既然系统的核心文件在客户机版本和服务器版本中本质上是相同的,那么,系统在运行过程中又是如何有所不同呢?简而言之,在默认配置下,服务器系统针对系统吞吐量做了优化,使之成为高性能应用服务器;而客户机版本呢,虽然它也有服务器的能力,但是它针对交互式桌面用途下的响应时间做了优化。而且,运行时的策略决策,在服务器版本和客户机版本中也是不同的。甚至线程调度中的有些细节在这两大产品族中也有不同的默认行为,比如时间片或者线程时限的默认长度。