Windows系统架构
操作系统模型
在大多数用户操作系统中,应用程序与操作系统本身是隔离的:操作系统代码在内核模式下执行,可以访问系统数据和硬件,应用程序代码运行在用户模式下,只有有限的接口可以使用,对系统数据访问受限,无法直接访问硬件。当用户模式的程序调用系统服务时,处理器会执行一条特殊指令,将发出调用的线程切换至内核模式。当系统服务完毕后,操作系统会将该线程的上下文重新切回到用户模式,让调用方继续运行。
和unix一样,windows系统大部分代码和驱动程序都是共享相同的受保护的内核模式空间。意味着操作系统任何组件,都可以破坏其他组件的数据。
Windows的大部分内核代码使用C语言编写。C语言不能直接支持面向对象的构造,例如多态函数或者类的继承,因为Windows中基于C语言的对象实现只是借助面向对象语言的一些特性。
架构概述
在这里会发现,有条线将操作系统分为用户模式和内核模式两部分。线条上部为用户模式,下部为内核模式。用户模式线程会在私有进程地址空间内执行(不过当它们在内核模式下执行时,将可以访问系统空间)。因此系统进程,服务进程,用户进程以及环境子系统都有自己的私有进程地址空间。
四种基本类型的用户模式进程如下:
- 固定的系统支持进程。例如登录进程和会话管理器。
- 服务进程。服务进程承载了Windows的服务,如Task Schedule和Print Splloer服务。
- 用户进程。用户进程可能是下列某种类型之一:Windows的32位或64位进程之一,windows3.1的16位进程,ms-dos 16位进程,posix32位进程或者os/2 32位进程。
- 环境子系统进程。这些进程实现了对操作系统环境的部分支持,这里的环境是指操作系统展示给用户的个性化部分。
子系统DLL:在windows系统中,用户无法直接调用原生的Windows操作系统服务,而是需要通过一个或者多个子系统动态链接库DLL调用。子系统DLL的作用在于将文档化的函数转化为相应的内部(t通常没有文档化的)原生系统服务调用,这些调用通常是在是在Ntdll.dll实现的。
Windows内核组件包含:
- Windows执行体(包含了操作系统的基本服务,例如内存管理,进程线程管理等)
- Windows内核(包含了底层操作系统函数,例如线程调度,中断,异常分发等)
- 设备驱动程序
- 硬件抽象层(消除不同平台的差异)
- 窗口和图形系统(实现GUI功能)
Windows核心组件的文件名:
可移植性
Windows一个设计目标是要能够运行在不同的硬件体系结构上。为了跨域不通硬件架构和平台实现可移植性,主要运用了两种方法:
- 分层式设计
- 使用C语言
对称多处理器
多任务是指让多个执行线程共享同一颗处理器的操作系统技术。
能够很好的在多处理器运行是windows 的设计目标。windows是一个对称多处理(SMP)操作系统。没有主处理器,操作系统和用户线程可以被调度到任何一个处理器上运行,而且所有的处理器共享唯一的内存空间。
对称处理和非对称处理不同,操作系统选一个处理器运行系统内核代码。而其他处理器运行用户代码。
可伸缩性
多处理器系统下,关键的问题是可伸缩性。windows有以下功能这些功能对windows作为一个多处理器起到关键性的作用:
1.能一个处理器上运行系统代码,也可以在多个处理器上运行。
2.在单个进程内执行多个线程,这些线程可以在不同的处理器上运行。
3.内核内部(如自旋锁,排队自旋锁以及压栈锁)以及设备驱动程序和服务器进程内部的细粒度同步,是的多个组件可以并行在多个处理器上运行。
4.如I/O完成端口之类的编程机制,是的可以实现高效的多线程进程,并且这样的程序再多处理系统上有很好的伸缩性。
客户和服务器版本区别
客户版和服务器版主要区别是有:
支持的处理器个数不同。
支持的物理内存不同。
所支持的并发网络连接数不同。
重要的系统组件
环境子系统和子系统DLL
环境子系统的角色在于将基本的Windows执行体系统服务的某些子集暴露给应用程序。此类子系统可供访问Windows原生服务的不同子集。这意味着在一个子系统的基础上建立的应用程序所能执行的某个操作,可能无法被建立在另一个子系统的基础上的应用做到。
每一个EXE都会绑定到唯一的子系统。
用户程序不能直接调用Winodw服务而是要通过DLL来调用
比如:windows子系统DLL(Kernel32.dll,advapi32.dll,user32.dll,gdi32.dll)。
当应用程序调用子系统DLL中的函数时,会出现下列三种情况之一:
- 函数完全在该子系统DLL中实现的,在用户模式下运行。
- 该函数要求调用windows执行体一次或多次。
- 该函数要求在环境子系统中完成某个工作。
子系统的启动
子系统是由会话管理器(Smss.exe)进程启动的。子系统的启动信息存储在注册表hklm\system\currentControlset\control\session manager\subsystems
键下。
其中Required值表示系统引导时需要加载的子系统。该值包含了两个字符串:windows和Debug。但是debug只是拿来占位置的,windows的指向Csrss.exe表示代表客户端/服务器运行的子系统(也就是我们常说的windows子系统)。
windows子系统
windows子系统包含下列组件:
- 对于每个绘画,环境子系统进程(Csrss.exe)的一个实例将加载4个DLL,包含下列支持:
- 与进程和线程的创建及删除有关的多种智能任务
- Windows应用程序的关闭
- 包含有关注册表位置映射的.ini文件
- 以windows消息的形式将某些内核通知信息发送给Windows应用程序
- 内核模式的设备驱动程序(Win32k.sys),用于提供以下支持:
- 窗口管理器
- 图形设备接口
- DirectX功能的封装函数
- 控制台的宿主进程(用于为控制台应用程序提供支持)
- 桌面窗口管理器
- 子系统DLL(如Kernel32.dll,advapi32.dll等)
- 图形设备驱动程序
NTDLL.DLL
NTDLL.DLL是一个特殊的系统支持库,主要被子系统DLL和原生应用程序使用(此处原生是指未绑定至任何特定子系统的映像)NTdll.dll包含以下两类函数:
- 系统服务分发存根,它们会调用Windows执行体系服务。
- 内部支持函数,供子系统,子系统dll以及其他的原生映像文件使用。
第一组函数是为windows执行体系服务提供接口,在用户模式下可以通过接口函数调用windows执行体的系统服务,如(NtCreatefile,NtSetEvent)
对于每个这样的函数,ntdll包含了一个同名入口,函数内部的代码包含了与处理器体系接口相关的模式切换指令,通过该指令可转换到内核模式下,从而调用系统服务分发器。分发器检查某些参数后,再调用真正的内核模式系统服务,其中包含ntoskrnl.exe内部实现代码。
NTDLL.DLL也包含了许多支持函数,比如映像文件加载器(以ldr开头的函数)、对管理器、Windows子系统进程通信函数(Csr开头的函数)、以及一般运行库(Rtl开头的函数)、也包含了异步调用(APC)分发器和异常分发器
原生映像
一些映像(可执行文件)不属于任何子系统。换句话说,它们并不链接至一组子系统DLL,例如Windows子系统的Kernel32.dll。相反,它们只链接至Ntdll.dll,这是横跨所有子系统的“最小公分母”。由于Ntdll.dll暴露的原生API大部分并没有提供文档,此类映像通常只能由微软构建,例如会话管理器(Smss.exe),它是由内核直接创建的第一个用户模式进程,因此不能依赖Windows子系统。
执行体
Windows执行体是Ntoskrnl.exe的上层(其下层为内核。)执行体包含下列类型的函数。
- 可在用户模式下导出和调用的函数
- 通过DebiceIoControl函数调用设备驱动器函数
- 只能在内核模式下导出的函数
- 可在内核模式下导出并调用
- 定义为全局符号但不可导出的函数
Windows执行体还包含以下组件:
1.配置管理器,复制系统注册表的实现和管理
2.进程和线程管理器,创建或者终止进程和线程。
3.安全应用监视器,强制在本地计算机上实行安全策略,它守护着系统资源执行对运行时对象的保护和审计。
4.I/O****管理器:实现了设备无关的I/O,负责将这些操作分发到恰当的设备驱动程序做进一步处理。
5.**即插即用(pnp)**管理器:为了支持一个特定的设备,确定驱动,并加载这些驱动。
6.电源管理器:负责协调事件,并且向设备驱动程序产生电源管理I/O通知。如电源管理器设备为系统空间,通过将cpu置于睡眠来降低电源电耗。
7.WDM Windows****管理规范例程:允许设备驱动发布有关性能和配置信息以及接受来自用户模式的WMI服务命令。
8.高速缓存管理器:提高了以文件为基础的I/O操作的性能,其做法是让最近引用过磁盘数据留在主内存中以便快速访问。(并且延迟了写操作,在将更新数据发送到磁盘前先在内存中停留一小段时间。)
9.内存管理器:实现了虚拟内存
10.逻辑预取器:加速系统和进程启动过程
另外Windows执行提还包含了4组主要支持函数:
1.对象管理器,创建,管理,删除Windows执行体对象和抽象数据类型,这些对象和数据类型代表了操作系统资源。
2.LPC****设施,在同一台机器上用户进程和服务器进程之间传递消息。
3.公共运行库,字符串处理,算术操作等函数。
4.执行体支持例程:如系统内存分配,互锁的内存访问,以及2中特殊的同步对象:资源和快速互斥体。
内核
内核是由Ntoskrnl.exe中的一组函数以及对硬件体系结构的低层支持构成的。Ntoskrnl.exe中的这组函数提供了一些最基本的机制。内核代码使用C编写,并不容易在C中访问的任务,则保留使用汇编。大部分函数都已经文档化,以Ke开头。
内核对象
内核给高层做支持。内核实现了操作系统最基本的机制(调度,分发)。把各种策略决定留给了执行体。
内核外看来,执行体将线程和其他可共享资源都表示为对象。这些对象要求一些策略开销。这些开销在内核中不存在,内核实现了一组更简单的对象,称为内核对象,帮助内核控制好中心处理过程,并且支持执行体对象的创建工作。执行体层的绝大多数对象包装了一个或者多个内核对象,把他们的内核属性合并起来。
一组内核对象建立了有关控制各种操作系统功能叫做控制对象,另一组内核对象融合了同步的能力,改变或者影响线程调度叫分发器对象。分发器对象包含了内核线程,互斥体,事件,内核事件对,信号量,定时器,等待定时器。
执行体通过内核函数创建内核对象实例,维护对象实例。构建更加复杂的对象提供给用户。
硬件支持
内核的另一个主要功能是将执行体和设备驱动程序从windows所支持的各种硬件体系结构中抽象出来,或者隔离出来变化的差异。
在内核设计是竟可能的使用公共代码最大化。内核支持的可移植性接口,在不同的体系结构上是等同的。而且实现这组接口的大部分代码,在不同的结构体系上也是相同的。但是有些代码和体系结构有关,如上下文切换。
从高层看线程选择和上下文切换可以使用相同的算法(上一个线程的执行上下文被保存起来,新线程的环境被加载进来),但在不同的处理器上,实现还是有差异的。执行上下文是由处理器的寄存器来描述的,所以要保存和加载哪些数据还是有差别的。
系统进程
以下系统进程会出现在每个windows系统中(其中空闲进程,system进程并不是完整的过程,因为它们不是运行在用户模式的可执行文件):
- IDLE进程
- system进程
- 会话管理器(Smsss.exe)
- windows子系统(Csrss.exe)
- 登陆进程(Winlogon.exe)
- 服务控制管理器(Services.exe)
- 本地安全认证服务(Lsass.exe)