首页 > 代码库 > 深入解析Windows操作系统笔记——CH2系统结构
深入解析Windows操作系统笔记——CH2系统结构
2.系统结构
本章主要介绍系统的总体结构,关键部件之间的交互,以及运行在什么环境。
2.系统结构
2.1 需求和设计目标
2.2 操作系统模型
2.3 总体结构
2.3.1 可移植性
2.3.2 对称多处理
2.3.3 可伸缩性()
2.3.4 客户和服务器版本的区别
2.3.5 版本检查
2.4 关键的系统组件
2.4.1 环境子系统和子系统dll
2.4.1.1 Windows子系统
2.4.1.2 POSIX子系统
2.4.1.3 OS/2子系统
2.4.2 NTDLL.DLL
2.4.3 执行体
2.4.4 内核
2.4.5 内核对象
2.4.6 硬件支持
2.4.7 硬件抽象层(HAL)
2.4.8 设备驱动程序
2.4.9 系统进程
2.4.9.1 空闲进程
2.4.9.2 中断和DPC
2.4.9.3 system进程和系统进程
2.4.9.4 会话管理器
2.4.9.5 Winlogon,lsass和Userinit
2.4.9.6 服务控制器管理
2.5 总结
2.1 需求和设计目标
略
2.2 操作系统模型
在大多数用户操作系统中,应用程序与操作系统本身是隔离的:操作系统代码在内核模式下执行,可以访问系统数据和硬件,应用程序代码运行在用户模式下,只有有限的接口可以使用,对系统数据访问受限,无法直接访问硬件。
和unix一样,windows系统大部分代码和驱动程序都是共享相同的受保护的内核模式空间。意味着操作系统任何组件,都可以破坏其他组件的数据。
当然用户程序和操作系统所有组件是隔离的。应用程序无法直接访问系统中特权部分的数据和代码。
windows内核模式组件也体现了基本的面向对象设计原则。如他们不会直接进入另一个组件的数据结构来访问该组件维护的数据。相反是利用正式的接口来传递参数,访问和修改相应的数据接口。
但是严格上来说windows并不是一个面向对象系统。windows内部使用c语言,并不是面向对象系统,c语言对象实现,只是借用了面向对象语言的特性。
2.3 总体结构
本节介绍windows的设计目标和包装方式,如下图windows总体结构中的关键系统组件。
有4中用户模式进程:
1.固定的系统支持进程,如登陆进程,会话管理器进程。
2.服务进程,宿纳了windows服务,如进程管理器和假脱机服务。
3.用户应用程序,有6个类型:windows32位,windows64位,windows3.1 16位,ms-dos 16位,posix32位或者OS/2 32位。
4.环境子系统服务进程,实现了操作系统环境的部分支持。这里的环境是指操作系统展示给用户或者程序员的个性化部分。
在windows下,用户程序不能直接访问原始的windows服务,要通过一个或者多个子系统动态链接库。
windows内核组件包含:
1.windows执行体,包含基本的操作系统服务,如内存管理,进程和线程管理,安全性,I/O,网络,跨进程通信。
2.windows内核,是由一组底层的操作系统功能构成,如线程调度,终端和异常处理分发。以及处理器同步。提供了一组例程和基础对象。执行体的其他部分利用这些例程和对象实现更高层次的功能。
3.设备驱动程序,硬件设备驱动程序,也包含文件系统和网络驱动程序。其中硬件设备驱动程序将用户的I/O函数调用转化为特定的硬件设备请求。
4.硬件抽象层,指一层特殊代码,它把内核,设备驱动程序和windows执行体其他部分跟与平台相关的硬件差异隔离开来。
5.窗口和图形系统:实现了图形用户界面函数。
文件名 | 组件 |
Ntoskrnl.exe | 执行体和内核 |
Ntkrnlpa.exe | 执行体和内核,支持物理地址扩展,是的系统可寻址64GB物理内存 |
Hal.dll | 硬件抽象层 |
Win32k.sys | Windows子系统的内核模式部分 |
Ntdll.dll | 内部支持函数,以及执行体函数和系统服务分发存根(stub) |
Kernerl32.dll,Advapi32.dll,User32.dll,Gdi32.dll | Windows的核心子系统DLL |
2.3.1 可移植性
windows的一个设计目标是要能够运行在各种不同的硬件体系结构上。
windows有2中方式支持可移植性以支持多种硬件体系结构和平台:
1.windows有一个分层设计,系统底层部分与处理器体系结构相关,或与平台相关的,这些部分被隔离到独立的模块中,所以搞成不需要考虑体系结构的区别。有2个组件为系统提供了可移植性:内核和硬件抽象层。
2.windows的绝大多数代码是由c语言编写的,少部分是使用c++编写的,只有那些需要直接与系统硬件通信的部分或者对性能极端敏感的操作系统部分,才是用汇编语言编写的。
2.3.2 对称多处理
多任务是值多个执行线程之间共享同一个处理器的操作技术。
能够很好的在多处理器运行是windows 的设计目标。windows是一个对称多处理(SMP)操作系统。没有主处理器,操作系统和用户线程可以被调度到任何一个处理器上运行,而且所有的处理器共享唯一的内存空间。
对称处理和非对称处理不同,操作系统选一个处理器运行系统内核代码。而其他处理器运行用户代码。
xp和2003支持2中新的多处理器系统:超线程(hyperthreading),NUMA(非一致性的内存结构)。
超线程是intel一个技术,可以一个物理处理器上有多个逻辑处理器,是的一个逻辑cpu可以在其他逻辑cpu正在忙着的时候继续运行。
在非一致性内存结构NUMA系统中,处理器被组织成更小的单元,成为node,每个结点都有自己的处理器和内存,并同一个一个缓存一致(cache-cohernet)的互联总线连接到更大的系统上。NUMA系统上的windows仍然作为一个smp系统运行。所有的处理器可以访问所有内存。不过本地结点比其他节点速度要快,系统想要提高性能做法是,根据现场用到的内存所在的节点,讲现场调度到同一个处理器上。
在windows的最初设计上32位最多只支持32个cpu,64位支持64个cpu。并没有本质的因素来限制处理器个数。注册表LocensedProcessors可以限制处理器个数。
考虑到性能问题内核和HAL分为2个版本,单处理器和多处理器版本。
在系统磁盘上的文件名 | 在发布介质上单处理器版本的名称 | 在发布介质上多处理器版本的名称 |
Ntoskrnl.exe | Ntoskrnl.exe | Ntkrnlmp.exe |
Ntkrnlpa.exe | Ntkrnlpa.exe in \windows\<arch>\Driver.cab | Ntkrpamp.exe in \windows\<arch>\Driver.cab |
Hal.dll | 取决于系统类型 | 取决于系统类型 |
以下只针对2000系统 |
|
|
Win32.sys | \I386\UNIPROC\Win32k.sys | \I386\Driver.cab中Win32.sys |
Ntdll.dll | \I386\UNIPROC\Ntdll.dll | \I386\Ntdll.dll |
Kernel32.dll | \I386\UNIPROC\Kernel32.dll | \I386\Kernel32.dll |
2.3.3 可伸缩性()
多处理器系统下,管家你的问题是可伸缩性。windows有以下功能这些功能对windows作为一个多处理器起到关键性的作用:
1.能一个处理器上运行系统代码,也可以在多个处理器上运行。
2.在单个进程内执行多个线程,这些线程可以在不同的处理器上运行。
3.内核内部(如自旋锁,排队自旋锁以及压栈锁)以及设备驱动程序和服务器进程内部的细粒度同步,是的多个组件可以并行在多个处理器上运行。
4.如I/O完成端口之类的编程机制,是的可以实现高效的多线程进程,并且这样的程序再多处理系统上有很好的伸缩性。
2.3.4 客户和服务器版本的区别
客户版和服务器版主要区别是有:
支持的处理器个数不同。
支持的物理内存不同。
所支持的并发网络连接数不同。
2.3.5 版本检查
略
2.4 关键的系统组件
已经看过上面的简易的结构图,了解了高层的结构体系。
之后都会围绕这个图展开,第三章解释windows使用的主要控制机制(如中断,对象管理器)。第五章启动和关闭windows的过程。第四章介绍各个管理机制(注册表,服务进程,WMI)。剩余的章节更加详细的讨论各个关键区域内存结构和操作(进程,线程,内存管理,安全性,I/O,存储管理,高速缓存管理器,windos文件系统和网络)。
2.4.1 环境子系统和子系统dll
如上图,最初windows有3个子系统,os/2,posix,wondows。os/2最后一次发布和Windows2000。到了xp posix也不发布了。3个子系统中windows子系统比较特别,是必须启动的。
查看注册表HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems下面有子系统的信息。
其中Required值表示了启动要加载的子系统,如上图,值为Debug和Windows。Window值包含了windows子系统的文件规范,csrss.exe它代表了客户/服务器运行时的子系统。Debug为空。Optional值为Os2,Posix表示这2个子系统,被按需启动。Kmode表示windows子系统的内核环境下运行的部分为win32k.sys。
环境子系统角色是将windows基础系统服务暴露给应用程序。每个子系统都提供了对于windows原生服务不同部分的访问能力。也就是说建立在某个子系统上的应用程序可以做到的,是另一个建立在不同子系统的应用程序无法做到的。如posix的fork。
每个exe可以执行映像被绑定到一个子系统上,如VC++ link命令/SUBSYSTEM可以指定类型代码,可以使用Exetype工具查看此类型代码。
用户程序不能直接调用windows服务而是通过dll来调用如windows子系统dll(kernel32.dll,advapi32.dll,user32.dll,Gdi32.dll),POSIX子系统DLL(psxdll.dll)。当一个应用程序调用子系统可能会发生3中情况:
1.函数完全在该子系统dll中实现的,在用户模式下运行。
2.该函数要求调用windows执行一次或多次。
3.改函数要求在环境子系统中完成某个工作。
2.4.1.1 Windows子系统
Windows子系统有一下几个主要组件构成:
1.环境子系统进程(Csrss.exe),包含下列支持:
a.控制台(文本)窗口
b.创建或删除进程和线程
c.对16为虚拟DOS机(VDM)进程的一部分支持。
d.其他一些函数,比如GetTempFile,DefineDosDevice,ExitWindowsEx,以及几个自然语言函数支持。
2.内核模式驱动程序(win32k.sys)包含:
a.窗口管理器,它控制窗口显示管理屏幕输出,采集来自键盘,鼠标,和其他设别的输入,同时也负责将用户的消息传递给应用程序。
b.图形设备接口,他是专门正对图形输出设备的函数库。
3.子系统dll
子系统dll,如Kernel32.dll,Advapi32.dll,User32.dll,Gdi32.dll,将windows api文档化,对应到Ntoskrnl.exe和Win32k.sys大多数未文档化的系统服务调用。
4.图形设备驱动
指硬件香瓜你的图形显示器驱动程序,答应及驱动程序和视频微端口驱动程序。
2.4.1.2 POSIX子系统
posix可以看成是一个基于unix的可移植的操作系统接口。值的是正对unix风格的操作系统接口的一组国际标准。posix鼓励厂商实现unix风格,编译在系统之间迁移。
需要使用posix子系统,要求使用platform sdk中使用posix的头文件和库文件。posix是按需启动的当第一次启动posix,psxss.exe要运行起来。posix的映像文件不是直接运行的。一个特殊的称为posix.exe的支持映像文件被启动起来,然后再创建一个子程序来运行posix应用程序。
2.4.1.3 OS/2子系统
和posix一样,有用性很有限,而且OS/2已经不在适用于windows了。
2.4.2 NTDLL.DLL
NTDLL.DLL是一个特殊的系统支持库,主要用于子系统DLL。包含两个类型函数:
1.系统服务分发存根(stubs),他们会调用Windows执行体系服务。
2.内部支持函数,供子系统,子系统DLL以及其他的原生映像文件使用。
第一组函数是为windows执行体系服务提供接口,在用户模式下可以通过接口函数调用windows执行体的系统服务,如(NtCreatefile,NtSetEvent)
对于每个这样的函数,ntdll包含了一个同名入口,函数内部的代码包含了与处理器体系接口相关的模式切换指令,通过该指令可转换到内核模式下,从而调用系统服务分发器。分发器检查某些参数后,再调用真正的内核模式系统服务,其中包含ntoskrnl.exe内部实现代码。
NTDLL.DLL也包含了许多支持函数,比如映像文件加载器(以ldr开头的函数)、对管理器、Windows子系统进程通信函数(Csr开头的函数)、以及一般运行库(Rtl开头的函数)、也包含了异步调用(APC)分发器和异常分发器。
2.4.3 执行体
Windows执行体是Ntoskrnl.exe中的上层,内核是其下层。执行体包含以下几类函数:
1.可在用户模式下调用的导出函数。这些函数成为(系统服务)并通过ntdll导出。还有一些未文档化的如LPC、NtQueryInformationProcess
2.可通过DeviceIoControl函数调用设备驱动器函数。
3.只能在内核模式下导出的函数,并且这儿写函数在Windows DDK或者Windows IFS Kit已经文档化。
4.在内核模式下调用,未在Windows DDK或者IFS Kit中文档化的导出函数。
5.定义为全局符号,但是未被导出的函数。如以Iop或者Mi开头的函数(分别是内部IO管理器支持函数和内部内存管理器支持函数)。
6.未定义为全局符号,而是在一个模块内容的函数。
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中特殊的同步对象:资源和快速互斥体。
2.4.4 内核
内核是由Ntoskrnl.exe中的一组函数以及对硬件体系结构的低层支持构成的。Ntoskrnl.exe中的这组函数提供了一些最基本的机制。内核代码使用C编写,并不容易在C中访问的任务,则保留使用汇编。大部分函数都已经文档化,以Ke开头。
2.4.5 内核对象
内核给高层做支持。内核实现了操作系统最基本的机制(调度,分发)。把各种策略决定留给了执行体。
内核外看来,执行体将线程和其他可共享资源都表示为对象。这些对象要求一些策略开销。这些开销在内核中不存在,内核实现了一组更简单的对象,称为内核对象,帮助内核控制好中心处理过程,并且支持执行体对象的创建工作。执行体层的绝大多数对象包装了一个或者多个内核对象,把他们的内核属性合并起来。
一组内核对象建立了有关控制各种操作系统功能叫做控制对象,另一组内核对象融合了同步的能力,改变或者影响线程调度叫分发器对象。分发器对象包含了内核线程,互斥体,事件,内核事件对,信号量,定时器,等待定时器。
执行体通过内核函数创建内核对象实例,维护对象实例。构建更加复杂的对象提供给用户。
2.4.6 硬件支持
内核的另一个主要功能是将执行体和设备驱动程序从windows所支持的各种硬件体系结构中抽象出来,或者隔离出来变化的差异。
在内核设计是竟可能的使用公共代码最大化。内核支持的可移植性接口,在不同的体系结构上是等同的。而且实现这组接口的大部分代码,在不同的结构体系上也是相同的。但是有些代码和体系结构有关,如上下文切换。
从高层看线程选择和上下文切换可以使用相同的算法(上一个线程的执行上下文被保存起来,新线程的环境被加载进来),但在不同的处理器上,实现还是有差异的。执行上下文是由处理器的寄存器来描述的,所以要保存和加载哪些数据还是有差别的。
2.4.7 硬件抽象层(HAL)
硬件抽象层是系统可移植的关键。HAL是一个可加载的,内模式模块提供了windows当前运行平台的低层接口。它隐藏了与硬件相关的细节,如I/O接口,中断控制器,以及多处理器通信机制等,体系结构或者机器相关的功能。
windows内部组件以及用户编写的设备驱动并不直接访问硬件,当它们需要获得与平台相关的信息时,它们可以通过调用HAL例程来保存可移植性。DDK中能找到很多有关HAL在驱动中的用法。
虽然windows带了几个HAL,但是安装时只能有一个被选中,并且copy到系统磁盘,其文件名为hal.dll。
2.4.8 设备驱动程序
设备驱动程序是可加载的内核模式(以.sys结尾),他们在I/O管理器和相应的硬件之间建立链接。驱动在内核模式下,位于以下3个环境之一:
1.在发起I/O功能的用户线程环境中
2.在内核模式系统线程的环境中
3.作为一个中断的结果(因此不存在任何特定的进程或者线程执行环境中)
驱动也是调用HAL,因此驱动程序可以在windows支持的cpu体系结构上代码级移植,在同一个体系结构族内是二进制可移植的。
设备驱动有以下几类:
1.硬件设备驱动程序,通过HAL操作硬件,从而输出到设备或者网络,或者从设备或者网络中输入。硬件设备驱动也有很多类型如,总线驱动,人机界面驱动等。
2.文件系统驱动程序是指可以接受面向文件的I/O请求,并将这些请求转化成针对某一特定设备的I/O请求。
3.文件系统过滤器驱动程序:如截取了I/O请求并且执行某些增值处理之后再传递给下一层驱动(执行磁盘镜像,加密的驱动程序)。
4.网络重定向器和服务器指文件系统I/O请求传递给网络上的某一台机器。或者从网络上接收此类请求的文件系统驱动程序。
5.协议驱动程序,如TCP/IP,NetBEUI,IPX/SPX之类的网络协议
6.内核流式过滤器驱动程序:这样的驱动被串接起来,以便对流数据进行信号处理。
驱动程序是内核模式中添加代码的唯一方式。
2.4.9 系统进程
以下系统进程会出现在每个windows系统中(其中空闲进程,system进程并不是完整的过程,因为它们不是运行在用户模式的可执行文件):
1.空闲进程
2.system进程
3.会话管理器(smss.exe)
4.windows子系统(csrss.exe)
5.登陆进程(winlogon.exe)
6.服务控制管理器(services.exe)和它创建的子服务进程(如系统提供通用服务宿主进程svrhost.exe)
7.本地安全认证服务器(lsass.exe)
2.4.9.1 空闲进程
空闲进程是第一个进程,并没有在用户模式下的实际映像文件。
2.4.9.2 中断和DPC
标记为中断和DPC(分发过程调用)用于中断和延迟过程调用的时间,他们并不是进程,列在这里是因为他们都会消耗cpu,并没有计算在任何一个进程中,而是被算在系统空闲中。
2.4.9.3 system进程和系统进程
system进程是一种特殊线程的母体。这些特殊线程只能运行在内核模式哦。系统线程有普通线程所有属性和环境,但是只运行系统空间中加载的代码。系统线程没有地址空间,因此动态存储空间,都必须从系统中内存堆分配,比如换页或者非换页池。
系统线程是由PsCreateSystemThread来创建的,这个函数只能在内核环境下才能被调用。
内核会创建一个称为平衡集管理器的系统线程,每秒没唤醒一次,可能发出调度和内存管理相关事件。告诉缓存管理器也使用系统线程来实现“预读”和”延迟写”功能。
在排查问题是,知道系统线程映射到某个驱动程序中,甚至映射到包含改代码的子例程中,一定非常有用。
所以如果system进程中的线程正在运行,首先要确定哪些线程在运行。通过线程看哪个驱动开始的或者检查调用栈,得知在运行到哪里了。
2.4.9.4 会话管理器
会话管理器(smss.exe)是系统中第一个创建的用户模式进程,由负责完成执行体和内核初始化工作的内核模式系统线程最后创建实际的smss.exe进程。
在windows启动过程中,会话管理器负责许多比较重要的步骤,如打开页面文件,执行延迟文件改名,删除操作,创建环境变量。将子系统程序(csrss.exe)和winlogon.exe启动起来。winlogon进程依次启动其他系统进程。
smss.exe的主线程执行以上步骤后,一直在csrss.exe和winlogon的进程上等待。如果这2个进程中任何一个非正常终止了,则ssms.exe让系统崩溃,(崩溃代码:status_system_process_terminated或0xc000021a)因为windows依赖这2个进程才能运行。
smss等待加载子系统的请求,调式事件,以创建新的终端服务器会话的请求。
终端服务会话是由smss来完成的。当smss接到一个创建会话的请求时,先调用NtSetSystemInformation,请求建立内核模式数据结构。又调用内部的内存管理函数MmSessionCreate该函数建立起会话虚拟地址空间,改地址空间包含会话中的换页池以及由win32子系统的内核模式部分和其他的会话空间设备驱动程序所分配,属于某个会话的数据结构,然后会为该会话创建winlogon和csrss实例。
2.4.9.5 Winlogon,lsass和Userinit
winlogon登陆进程处理交互式用户的登陆和注销,当sas被按下(ctrl+atl+del),winlogon接到一个用户登陆请求。
登陆过程的身份识别和认证是在一个名为GINA(图形识别和认证)的可替换DLL中,windows的标准为GINA为Msgina.dll实现了默认的windows登陆界面。然而开发人员可以提供他们自己的GINA DLL来实现其他的身份识别和认证机制如:基于声波的方法。
一旦用户名和口令捕捉到了就可以送到本地安全认证服务器进程(lsass.exe)进行认证。lsass调用适当的认证包,以执行实际的验证操作,比如口令是否符合存储在活动目录或者sam中的口令信息。
在成功完成验证后,lsass调用安全引用监视器中的一个函数(如:NtCreateToken)创建一个访问令牌对象。对象包含当前用户的安全范围。winlogon利用此访问令牌来创建该用户会话中的初始进程默认为userinit.exe。
userinit执行该用户环境的一些初始化工作,然后再查找注册表winlogon下的shell并且创建一个进程来运行系统定义的外壳程序(默认explorer.exe)
然后userinit退出,这就是explorer.exe没有父进程的原因。winlogon在注销,登陆,sas winlogon是活动的。关于登陆过程各个步骤的完整秒死可以看第5章。有关安全认证可以查看第八章。
2.4.9.6 服务控制器管理
windows中的服务可以自一个服务器进程,也可以是一个驱动程序。这一指的是用户模式进程(如:unix的守护进程),这些进程可以在系统引导是自动启动起来,而无需交互式的登陆过程。也可以被配置为手动启动。
服务控制器是一个特殊的系统进程,用于启动,停止服务进程也复制服务进程之间的交互。服务有3个民粹:运行中进程名,注册表内名称以及管理器的显示名。
在服务进程和所运行的服务之间并不是一一对应的,因为有些服务和其他共享一个进程。注册表服务类型代码指明了共享还是独占进程。
许多windows组件使用系统服务实现如Spooler,event log,Task Scheduler和多个网络组件。
2.5 总结
本章主要概括的介绍了一遍windows体系结构,检查了一遍关键的组件,他们之间是如何联系起来的。
深入解析Windows操作系统笔记——CH2系统结构