到底改进了什么?Win7/2008 R2核心剖析
[转自IT168]Windows 7/Windows Server 2008 R2发布已经有近一个月了,加上RC/beta阶段,相信很多人都已经接触或者使用过了。很多人都已经知道在界面,以及DirectX、图形架构上的改进,然而却很少有清晰、令人信服的资料,说明操作系统变得更快强、更强、更稳定,有的只是功能变的更加复杂了。有没有最基本、最核心的改动,可以让人们决定升级到新的版本呢?
Windows Server 2008 R2,和Windows 7基于相同的内核,当然后面可以看到,它们还是有些区别的
Windows Server 2008 R2
大致上,4~5年就会有一个Major Release(主要发布),而每两年多就会有一个Release Update(发布升级)
较老的路线图
从路线图上可以看出,Windows 7和Windows Server 2008 R2都属于发布升级,而之前的Vista/Server 2008则属于主发布。不过,从下面的资料以及从后面的文章内容上看,其实更新的东西还是挺多的。Windows 7/Server 2008 R2的6.1的版本号有部分的因素是考虑到兼容性。一些程序会需要检查主版本号(6)。
和Vista/2008版本号仅增加0.1的版本号主要是为了兼容性
下面我们将会看到Windows NT内核上的多种变化,主要目标放在了NT 6.1(Windows 7和Windows Server 2008 R2)上,但是也会涉及到NT 6.0(Windows Vista和Windows Server 2008)和NT 5.0(Windows XP/Windows Server 2003)。首先我们会看到的是对Windows NT架构的简要描述。
在谈及Windows的内核的时候,我们首先介绍一下Windows NT的架构。Windows 9x系列采用的是单内核的设计,而Windows NT则是微内核的设计,它们是很不相同的。如Windows 2000、Windows XP/Windows Server 2003、Windows Vista/Windows Server 2008一直到现在的Windows 7/Windows Server 2008 R2,都是基于、沿用了Windows NT的架构设计。
在199x年,微软与IBM合作开发OS/2决裂,之后,微软来自原DEC的人马开始专心制作盖茨梦想中的操作系统,新的操作系统部分基于OS/2 3.0,同时还带有DEC VMS的因素,这个操作系统被命名为Windows NT,NT就是New Technology新技术的意思。
Microsoft Windows NT 3.1,1993年,一直到现在,发展了16年
为此什么称之为NT呢?Windows NT采用了全新的设计思想,这牵涉到操作系统内核上的理念。在80年代前,主流的操作系统,要么是属于原始的没有内核的产品,要么属于单内核产品,到了80年代,学术界开始流行一种微内核的风潮,出现了如Mach(1985年)这样的经典微内核操作系统。典型的单内核系统则有各种Unix和类Unix。
在一个分层设计的操作系统中,为其他组件提供最基本的系统功能的部件就叫做内核。单内核就是单个大的进程映像中集成了操作系统中所有基础功能,而微内核就是在内核中仅集成了经过挑选的、基本的功能,其它的操作系统功能构建在其上——用户应用程序再构建其上。微内核的设计可以让系统变得更模块化,带来可移植性和新功能开发上的好处,此外操作系统层次更明晰,维护也会更加方便。
在用到新的微内核设计的同时,Windows NT就需要采用流行的双模式(Dual Mode)设计,整个系统分成两部分运行在两种特权等级下。两种特权等级分别是用户模式(User Mode)和监察者模式(Monitor Mode)或者系统模式(System Mode ),后者通常叫做核心模式(Kernel Mode)。操作系统的大部分都运行在核心模式,而用户程序则运行在用户模式,受到操作系统的监视、控制。
微内核架构:Windows NT架构图,适合3.1~3.51版本
不过,Windows NT的架构和传统的、纯粹的微内核架构还是有些不同。如Minix/Amoeba这样的纯微内核设计的内核非常之小,只包含了系统最基本的功能,并且只有它们运行于核心模式,其他系统部分都以服务的形式运行在用户模式。而Windows NT当中,除了内核运行于核心模式之外,还有一部分重要的系统功能也运行于核心模式,这部分不包含在内核当中却运行于核心模式的功能部分就叫做Executive(执行体),包含了对象管理器、安全监视器、进程管理器、虚拟内存管理器以及LPC机制,此外,文件系统、IO管理器以及大部分的驱动程序也都包含了在内。令驱动程序运行在执行体是导致了Windows NT不稳定的一个重要因素之一,由于运行在核心模式,驱动程序可以运行特权指令,设计不当可以很容易地导致问题乃至造成系统崩溃。并且驱动程序并不是由操作系统提供,而是由第三方厂商提供,因此其安全性和稳定性难以得到完全的保障。一些微内核架构系统的驱动程序运行在用户模式。
Windows NT内核, 适合3.1~3.51版本
作为一个以GUI为根本的操作系统,图形性能是基础。在通常情况下,微内核的性能比单内核性能要低,因为单内核通过系统调用而微内核通过消息传递。虽然Windows NT发布的时候采用了特别的方式改进了图形性能,如优化的消息传递协议LPC(Local Procedure Call,本地过程调用,用来和RPC对应),并且还从中特别创造了Quick LPC,通过事件对(Event Pair)这个特别的结构来加速CSR subsystem(Win32子系统)的图形操作。然而微软感到还未足够,到了1996年发布的Windows NT 4.0,微软将图形相关的部分从用户层放入了内核层:
Windows NT 4.0架构图,带颜色的部分在之前的版本中原本属于CSR subsystem的一部分;Windows NT 4.0之前,驱动程序也有一部分在用户层
在Windows NT系统中,所有的图形界面操作都和Win32子系统(上图是CSR subsystem)相关,系统通过调用Win32子系统的GDI(Graphics Device Interface,图形设备接口)API,然后GDI部件调用显卡驱动来实现图形操作,后一种调用比前一个调用频繁的多,因为一个简单的GDI命令需要和显卡驱动进行频繁的交流来完成。在Windows NT 4.0之前,GDI和搭配的USER、WIndows管理器都在CSR subsytem进程中,也就是在用户层,因此图形操作会需要频繁地在用户态和核心态之间切换,引起很多的系统开销。而在Windows NT 4.0中,只有数量相对较少的GDI API调用会导致用户态和核心态之间切换,因此图形性能得到了很明显的改进。如PowerPoint的性能就提升了15%-20%。在“便宜”的高端工作站上,Windows NT 4.0开始和Unix竞争。Windows NT 4.0的内核的大架构一直沿用到现在。
*Windows Vista在LPC机制当中还引入了一个新的ALPC(Advanced Local Procedure Call)。 相信没听说过进程和线程概念的人应该很少,作为程序运行的实体,我们每天都在不停地创建、运行进程和线程。
Windows NT基于内核级线程模型,所有的线程都由内核管理调度,这个调度由内核的叫做Dispatcher分发器(也叫Scheduler调度器)的部件完成进行。进程的调度则由位于执行体的进程管理器来完成。
Dispatcher管理着线程的列表,以及各种时钟,如下图所示,Windows Server 2003也就是Windows NT 5.0具有一个大的Dispatcher Lock,下面管理着多个Timer Lock。Lock锁是一个共享/同步机制,同一时间只能有一个拥有者获得一个锁,并获得锁代表的系统资源。锁的概念让多线程的编程模型变的简单,然而却不利于并行运行,因为在一个拥有者获得资源的时候,其他用户只能等待,无所事事。Windows Server 2003确保了同一时间只能由一个线程来修改相关的状态,以及定时器:
虽然Windows NT一开始就支持多处理器,然而多个CPU上的线程必须排队等候获得Dispatcher的锁
到了Windows Server 2008(也就是NT 6.0),修改各种定时器终于不再需要先获得Dispatcher的锁了,分散的锁让2008的多线程性能有所提升。如同配置的终端服务器上,2008可以比2003支持30%多的并发用户
Windows Server 2008相对Windows Server 2003在锁上面的改进不算太大,没有动到筋骨,然而Windows Server 2008 R2上的变动可就大了:Windows Server 2008 R2彻底去掉了Dispatcher的锁。
在Windows Server 2008 R2上,以往的单个Dispatcher锁被更细小的、以对象为单位的小锁代替,同时还有很多的操作是无锁化的,这些都彻底提升了多线程的运行性能。
去掉Dispatcher锁是2008 R2支持更多逻辑处理器的根本原因之一,Server 2008只能支持64个逻辑处理器,Server 2008 R2则能支持到256个,并且随着逻辑处理器的增加,性能具有着接近线形的提升
*一个逻辑处理器同时只能运行一个线程
除了去掉Dispatcher的锁之外,Windows Server 2008 R2还去掉了内存管理器(位于执行体)的PFN的锁,PFN是Physical Frame Number的意思,它跟踪着所有内存页面的状态,去掉这个锁之后,多个线程将可以同时分别对不同的内存页面进行操作,这也是提高多线程并发运行能力的一个重要改进。如下面连接所示,Windows 7的系统性能提升虽说有着图形架构上改进的因素,然而内核上的变动也是有影响的。锁的改动同时对Windows 7和Windows Server 2008 R2都有效。 如前面所述,由于两个大锁的消除,Windows Server 2008 R2可以支持到更大的多核系统。在之前的系统中,OS最高支持的逻辑处理器数量是用一个字长来表示的,如32位Windows只能支持32个逻辑处理器,64位Windows只能支持64个逻辑处理器:
但是Windows Server 2008 R2能支持到256个逻辑处理器,为了同时能和之前的应用程序兼容,2008 R2引入了处理器组的概念,它同时能支持到4个逻辑处理器组,老的应用程序可以不加改动就和以往一样使用最多64个逻辑处理器,而新的应用程序可以通过新的API使用完全的256个逻辑处理器。
128逻辑处理器的示意图
设想一个8路8核心、带超线程的Nehalem-EX平台,将会有128个逻辑处理器,这时候你就必须使用Windows Server 2008 R2,而不能使用Windows Server 2008了:
在具有单个大锁的时候,如此之多的处理器对系统来说是很难发挥作用的,因为一个逻辑处理器在修改线程运行状态的时候会导致所有其它处理器都处于Spinlock自旋锁的忙等待状态
估计知道DPC(Deferred Procedure Call,延迟过程调用)的人不多,不过对驱动程序架构有了结的人应该会知道,Windows NT的硬件中断处理和其它系统有些不同,它分为两个部分,一个是直接的ISR(Interrupt Service Routine,中断服务例程),以及DPC。重要的如电源失效、运算出错、硬件时钟等硬件中断必须立即进行处理,它们触发后将通过ISR中断等级较低的处理过程得到优先执行,而一些不怎么重要的硬件中断则不会立刻执行,而是会放在另外一个队列当中,稍后有空的时候再来执行,这将可以降低频繁的高等级中断导致其它中断等待时间过长、响应过慢的问题,如下图所示:
根据IRQL(Interrupt Request Level中断请求等级)来排序硬件的重要性,数字越大,等级越高,其中断执行就越优先;DPC和通常的线程调度属于同一个等级
虽然知道的人不多,但是人们其实对ISR和DPC应该都有过最直接的感受:在老的机器当中进行大量的IDE磁盘操作时,或者以超高的速度下载资料时,人们会感受到系统的响应将会明显变慢,甚至就像死掉了一样——有时候会真正的死掉。在这个时候,用户可以观察到程序占用的CPU,真相就是,CPU都被ISR和DPC占用了。ISR和DPC通常包含在驱动程序内,由硬件厂商提供,DPC可以抢占普通的线程,设计不好的驱动程序将会导致很糟糕的用户体验,以及性能。
ISR/DPC的详细执行架构:
1:设备触发一个中断,引发Trap Handler处理
2:等待Interrupt Dispatcher处理
3:进入ISR中断服务例程处理
4:较低IRQL的中断或者较高IRQL的中断中不需要立即执行的部分则加入DPC队列
5:高IRQL的中断立即进行处理
6:高优先级的事务都处理完之后,Thread Dispatcher(就是前面去掉了一个大锁的那个,这个锁也影响到了DPC)在普通线程切换重新获得控制权的时候产生一个DPC软中断
7:控制权交给DPC Dispatcher
8:开始处理DPC队列
9:DPC完成
到了Windows Server 2008 R2,DPC相关的处理也有了改进,如下文所示,不得不说,这个Tech·ED 2009的中文文档翻译非常糟糕,几乎面目全非。有条件的应该观看最后给出的英文原稿:
在Server 2008 R2之前,虽然每一个处理器上面都可以运行DPC,但是具有一个统一的DPC定时器,以及对应的定时器的锁,它运行在系统的CPU0上,显然,这是一个瓶颈,特别是在虚拟化应用场景下,多个虚拟机的DPC定时器也都依赖于这个独特的CPU0。在Server 2008 R2之上,但一的DPC定时器队列被拆散成多个队列,并运行在多个CPU上。具有大量IO硬件,以及虚拟机的系统将会获得明显的益处,遗憾的是,这个改动只对2008 R2有效,Windows 7无法享受到。这也是在多CPU、大量设备的系统中Server 2008 R2比Windows 7更好的一个原因之一。对于一些高端发烧友而言,2008 R2是一个值得推荐的选择。
*对于路过的Linux专家,必须得说,Linux 2.6有类似的机制,虽然没有一个像Windows这么一致的层次驱动程序架构。因此Linux的异步I/O显得略微粗糙一些。 Windows 7/Server 2008 R2的用户级线程调度实现其实不是一个发生在内核层面上的改进,因为它并没有去掉内核级线程调度。User Mode Scheduling,用户级调度,就和教科书上说的一样,通过避免频繁切换进内核来降低进程切换的消耗,从而获得很好的运行性能,同时避免一些内核的锁操作获得更好的并发性能。
可能知道的人很少:Windows NT一直提供了用户级线程的支持,它被称为Fiber,中文名叫做纤程。Fiber就是纤维的意思,把它叫做纤程的确很妙,纤程是比线程更细小的运行实体,一个线程可以分成多个纤程来运行。实际上,在Windows NT当中,程序的运行层次有四个:Task任务、Process进程、Thread线程、Fiber纤程。不过中间两个用的最多,两头的用的最少。
Fiber,和传统的用户级线程一样,缺点就是内核并不知道它的存在,而只知道线程的存在(因为Windows NT基于内核级线程模型),当一个Fiber执行一个堵塞自己的系统调用的时候,它堵塞住了整个线程乃至所有其它的纤程,这样内核就会挑选其他的线程运行,当堵塞解除的时候内核并不知道如何返回对应的纤程,因为内核只保留了线程的状态而不没有纤程的状态,基于这样的原因,纤程很少有人使用
在Server 2008 R2上,实现了用户级线程调度,而不是之前的那样,仅仅提供了用户级线程而没有提供相关的调度机制。用户级线程调度通过彻底分离线程的内核模式部分和用户模式部分,并分别提供一个调度器来实现。实际上Server 2008 R2提供了一个内核/用户级线程混合的调度模型,类似的系统有历史上的Mach;使用用户级线程调度的还有5.x~7.x版本的FreeBSD
传统的WinNT内核级线程调度,一个线程可以在用户模式和内核模式间切换,因此在两个模式下都具有相关的运行状态
老的模型在切换线程时,会同时切换内核和用户模式下的状态,而用户级线程调度上,不同的线程切换平时只是在用户模式进行切换,只有在进入内核模式的时候,才切换对应的状态,从而获得了用户级线程低消耗的好处
不过遗憾的是,UMS用户级线程调度只有在64位上提供,也就是Windows 7 x64和Windows Server 2008 R2上可用,Windows 7 32位没有这个功能。 Heap,堆,是一个数据结构,用来保存各种各样的数据,堆污染(Heap Corruption)是系统不可靠的一个主要原因,15%的用户模式崩溃、关闭过程中30%的用户模式崩溃都由它引起,并且非常难于分析和修复。
Windows Server 2008 R2提供了一个新的特性叫做FTH(Fault Tolerant Heap,容错堆)来减缓这个问题,虽然它主要是为开发者准备,不过对最终用户也有一些作用,在监测到堆污染后,系统将会对崩溃的程序进行监视以及应用一些特别的措施。
在可靠性方面,Server 2008 R2在内核之外还有一些改进,如DWM模型的改进、降低图形驱动导致的崩溃等,见:比Vista更完善 Windows 7图形架构解析,此外,Server 2008 R2当中,系统缓存、分页池以及系统代码现在具有了独立的Working Set,之前它们是公用一个Working Set,这对可靠性以及性能都有些好处。 我们已经谈及了Windows 7/Windows Server 2008 R2在核心上的多个改进,如两个大锁的去除,提升了多线程运行的性能并提高了系统的多核扩展性,这很符合现下处理器走向多核、并行处理的现状。为了更好的并行处理,DPC等个方面也有所改进。总体而言,不管你有多么喜欢Windows XP,Windows 7/Windows Server 2008 R2可以更好地配合现在的新硬件,功能更强,性能更好。
Windows Server 2008 R2,2009年10月22日
透过前文,我们也可以发现,有些特性只有Windows Server 2008 R2才具有,客户版的Windows 7缺少DPC分布式定时器,32位Windows 7缺少用户级线程。对于一些发烧友来说,Windows Server 2008 R2也是一个可以选择的桌面系统。而对于原来的桌面PC/服务器,Windows 7/Windows Server 2008 R2是一个值得升级的对象,当然,这最后还要取决于你愿不愿意花升级的钱。
大约会于2012年推出的Windows 8应该会有更大的改进,XP用户,你要等到那时候吗?
页:
[1]