了解WINDOWS内核的关键组件和功能
通过WRK可以了解到,WINDOWS内核绝大部分源代码是由C语言实现,只有部分与处理器相关的调度代码是通过汇编语言实现。最近半年我对WINDOWS平台本身有很高的兴趣,其实我作为应用程序开发人员对于WINDOWS内核没有必要知道的太多,但是了解下不仅对我应用程序排查问题有帮助,而且WINDOWS内核中有很多良好的设计也是我们应用开发人员值得学习的,例如说内存堆管理,IO体现等,甚至可以引用到自己的项目中。很多程序员和架构师每天围绕WINDOWS展开工作,因为我们的程序就是基于WINDOWS的,WINDOWS占领了PC的市场,关键是不得不用。我们开发的程序可以认为是WINDOWS能力的扩展,在WINDWOS平台下的主要扩展方式有以下几种:窗体应用程序,控制台应用程序,服务程序,驱动程序(可以认为是内核模块的扩展),本地程序。
1.扩展类型
窗体应用程序:这个大家最熟悉不过了,直接用MFC写一个窗体程序,用Winform写一个窗体程序。窗体程序一般都需要在某个用户的Session的桌面中运行,基于WINDOWS子系统,采用GDI做显示输出技术,基于WINDOWS的消息机制,有消息循环和窗体函数,所以窗体程序会有大量的GDI对象生成,窗体应用程序也是WINDOWS作为客户端系统最为普遍的应用。
控制台应用程序:控制台的程序是最早的DOS下16位应用在WINDOWS下的兼容方式(不过现在已经是32位为主了),有标准输入,标准输出和标准错误,一般是作为计算机管理人员使用。控制台程序与WINDWOS窗体应用的运行机制完全不同,窗体程序是基于GDI,内核级由win32k.sys处理,而控制台应用程序一般由csrss.exe(下文会有介绍)管理。
服务程序:这是WINDOWS作为服务器端应用时普遍采用的方式,具有守护特性(无需用户登录无需退出),类似与LINUX下的DAEMON进程,服务程序的运行不需要用户登录,一般由LOCAL SERVICE,NETWORK SERVICE,SYSTEM用户运行,所以没有用户界面,所以成为服务器端的主要应用方式是因为这种服务程序很多都是使用线程池来做IO处理,例如处理网络连接和数据库操作等。此前之前有人试图在WINDOWS服务中启动用户界面程序,虽然可能通过一些技巧会实现,但是这种不是服务程序设计的初衷,只能说明应用架构设计的不合理。
驱动程序:这里的驱动程序特指运行在WINDOWS内核模式下的扩展模块或设备驱动程序,WINDOWS内核通过IO管理器等执行体模块对驱动程序进行管理,可以是协议驱动程序,设备驱动程序,文件系统驱动程序等,一般基于一定的驱动程序开发模型由第三方提供。此外WINDOWS对于驱动程序的一个映像只允许加载一次,也就是说两个驱动程序不能使用同一个映像文件。
本地程序:这个可能大家最为陌生,本地程序不是我们常说的WIN32本地程序,WIN32本地程序是指基于WINDOWS子系统的本地代码程序。而这里的本地程序是WINDOWS的原生程序,一般直接基于ntdll.dll,而不是基于user32.dll,kernel32.dll等子系统dll。举个例子就是WINDOWS的第一个用户态进程smss.exe,完成会话管理任务和启动一些其他子系统进程。还有就是我们常用的瑞星杀毒软件在启动的时候会执行内核扫描,实际上这个程序就是本地程序。
所有以上程序都可以使用VS开发,只是改变一些配置选项,需要安装例如WINDOWS SDK和WINDOWS DDK等开发包。
其他一些扩展,例如WINDOWS的SHELL程序explorer.exe的扩展,IE浏览器的插件,还有就是登录认知的GINA扩展等。目前SHELL编程已经成为独立的开发方向。
2.内核模块
看一副经典的图片吧,这是一幅WINDOWS内核组件的原图,这里的内核是指大内核,而不是图中的kernel的微内核,微内核是特指线程调度模块。
在WINDOWS中可执行的代码在CPU上运行时会有用户模式和内核模式两种,CPU不是工作在内核模式就是工作在用户模式,一般用户模式在CPU的低权限级别运行,当线程运行在用户模式时只能访问进程空间的资源,对于32位系统只能使用2GB以下地址空间(最大3GB),如果需要访问其他资源需要陷入内核模式。当线程工作在内核态时能够访问到4GB全地址空间,包括系统空间的映射。图中NTDLL正是将用户态和内核态隔开的模块,NTDLL通过特殊的CPU指令可以进入内核态,反之亦然。
用户态中包括应用程序,子系统,服务和一些系统管理进程,最后都是通过NTDLL进入内核态的。
内核态中包括SDT(服务分发表,系统线程),执行体(包括内存管理,进程线程管理,IO管理等),微内核(调度)。此外还包括第三方的驱动程序(其实很多也是MICROSOFT提供的),和WINDOWS的子系统内核模块win32k.sys。
内核态还有一个很重要的hal.dll,实现WINDOWS内核的跨平台(硬件平台)。
3.重要文件
Ntoskrnl.exe: 包含执行体和内核部分,是大内核的主要部分,完全运行在内核态,可以说是WINDOWS系统的核心部分。WRK的源代码就是这一部分。
Ntkrnlpa.exe (32位): Ntoskrnl的PAE版本。
Hal.dll:硬件抽象层,WINDOWS的跨平台特性很多就要从这个文件说起,一共大概4个版本,在WINDOWS系统安装时会根据硬件平台选择一个进行拷贝之后重命名。
Win32k.sys: WINDOWS子系统的内核部分,包括了消息,图形的内核部分等。窗口显示;鼠标、键盘输入接收;传递用户消息,GDI。
Ntdll.dll:用户态子系统DLL。
Kernel32.dll,Advapi32.dll,User32.dll,Gdi32.dll:一些用户态的WINDOWS子系统DLL,WINDOWS共支持三种子系统WINDOWS,POSIX,OS/2。将documented Windows API映射到undocumented的kernel-mode system service call。
Csrss.exe:Console管理,创建/销毁进程和线程,支持16位进程。
Ntdll.dll:User-mode应用调用到Windows executive system service的接口,Subsystem, native images的内部支持。
Idle process:一个CPU一个线程,用来计算CPU空闲时间,进程编号为0,一般由WINDOWS的初始化程序退化而成。无映像文件。
System process系统,进程编号为4,一些系统线程会被附加在此进程中,无映像文件。
Smss.exe:第一个user-mode进程。
Winlogon.exe:登录界面。可替换。GINA。
Services.exe and Svchost.exe:服务管理和宿主进程。
Lsass.exe:验证用户登录信息。
Userinit.exe: 初始化用户信息,执行shell程序(explorer.exe)。
4.重要部分
内存管理
同步和线程调度
IO系统
服务分发
进程通信
网络系统
文件系统
WINDOWS子系统
5.推荐资源
《WINDOWS核心编程》
《深入解析WINDOWS内核》
《WINDOWS内核原理与应用》
Sysinternals工具