Windows NT 内核基本结构

简介:
Windows NT 内核基本结构和特征
尽管大部分人每天在Windows系统上工作学习娱乐,但是对于其内核结构很多人仍然是不了解的。一方面是由于其内核源代码不开源,另一方面则是由于相关资料的奇缺。我大二基本上花了一学期来学习和探究NT内核。虽然不敢说自己对其有很深入的了解,但至少其基本结构还算是清楚的。但是我毕竟才学有限,肯定会有不完善的地方,还请各位不吝赐教。
目前微软所有的主流操作系统均是基于NT内核,比如:
Windows 2000/XP/Server 2003(基于NT5)
Windows Vista (基于NT6)
Windows 7(基于NT6.1, 我没装过Win7,不过据说是这样的)

尽管很多人责备Windows在一些方面存在很多问题,但是这并不是内核的错,总的来说,NT的是一个成熟稳定且先进的内核,我认为在今后相当长的一段时期内,NT内核仍将是主流,且不会有很大变化(当然,局部的升级是完全毫无疑问的)
微软早期希望把NT做成一个纯微内核结构,关于微内核和单一内核的区别,各位如有不清楚的,可以去网上搜索一下。后来为了提高图形子系统的性能,避免大量的内核态和用户态切换,微软便将其移入内核之中,使其成为内核一部分(类似的还有后来的DirectX技术)。由此可见,NT并不是一个完全的微内核,它也具有单一内核的某些特征。

NT内核具有以下几个特征(摘自Undocumented Windows NT)
Portability (可移植性)
如你所知,Windows NT 可以运行在多种平台上,即 Intel、MIPS、Power PC 和 DEC Alpha。众多厂商都为 Windows NT 的可移植性做出了贡献。 其中最为重要的因素可能是其实现所使用的语言。Windows NT 大部分是用 C 语言编写的,也有一部分用的是 C++。 平台相关的汇编语言只在必需的地方才用到。Windows NT 团队还将操作系统中硬件相关的部分与其它部分隔离开,单独放进了 HAL.DLL。 如此一来,Windows NT 中与硬件无关的部分的代码就可以用 C 之类的高级语言来编写,也因此可以很容易地移植到各种平台。

Extensibility(可扩展性)
Windows NT 具有很高的可扩展性,但因为缺少文档,其可扩展的特性却极少得到发掘。未公开的特性的名单中,子系统首当其冲。子系统在操作系统中提供了多种操作系统接口。只需添加新的子系统程序就可以为 Windows NT 扩展新的操作系统接口,但是对于公开添加新子系统过程的要求微软却一直打马虎眼。

Windows NT 的内核是高可扩展的,因为可以将内核模块作为驱动程序动态加载。对于 Windows NT,微软提供了足够的文档来编写硬件设备驱动——即硬盘驱动、网卡驱动、磁带机驱动等等。在 Windows NT 下还可以编写不控制设备的驱动程序。甚至连文件系统也是作为驱动程序加载的。
Windows NT 的可扩展性的另一个例子就是系统调用接口的实现。 开发者要修改操作系统行为,一般都需要钩挂或添加系统调用。 Windows NT 的开发团队实际了良好的系统调用接口以方便钩挂和添加系统调用。但是微软还是没有公开这些机制。

Compatibility(兼容性)
长久以来,向下兼容性都是 Intel 处理器和微软操作系统的一大特征,也是这两位巨人成功的关键。Windows NT 必须能运行 DOS、Win16 和 OS/2 的程序。兼容性是 Windows NT 开发团队使用子系统概念的另一个原因。除二进制兼容之外(执行不同格式的可执行文件),Windows NT 还为符合 POSIX 的程序提供了源代码级的兼容。增强兼容性的其他方面还表现在除自己本身的 NTFS 外,Windows NT 支持其它的文件系统,如 DOS 的 FAT 和 OS/2 的 HPFS。

Maintainability(可维护性)
Windows NT 的代码量很大,维护着些代码的工作量也相当大。NT 的开发团队通过使用面向对象的设计实现了高可维护性。再有,将操作系统的功能分成各个层也提高了可维护性。最上面的一层,也就是用户见到的操作系统层面,是子系统层。子系统提供系统调用接口来为外界提供应用程序编程接口。在系统调用接口层之下的是 NT 的 executive,executive 又建立在内核之上,而内核又依赖于硬件抽象层(HAL),硬件抽象层与硬件直接通讯。
NT 的开发团队所选的编程语言也与 Windows NT 的可维护性有关。正如我们前面提到的,整个操作系统都是用 C 和 C++ 来编写的,只有极少数不用不行的地方用了汇编语言。

Security(安全性)
Windows NT 是一个安全的操作系统,是因为它有以下几点特征:用户在使用系统之前必须先登陆。 系统中的资源都被视为对象,而每一个对象都相应由一个安全描述符。安全描述符有一个安全列表来指示那些用户可以访问该对象。

尽管有这些,要是没有一个安全的文件系统,操作系统也不能说是安全的。 DOS 时的 FAT 文件系统没有预见到任何的安全问题,其作为一个单用户的系统,也不用防范安全问题。

为了克服此缺陷,Windows NT 团队推出了一种新的文件系统,这种文件系统基于 OS/2 的文件系统 HPFS。这种新的 Windows NT 的自有文件系统叫 NTFS。它支持访问控制,用户可以为 NTFS 下创建的文件或目录指定访问权限,NTFS 只允许有访问权限的进程访问该文件或目录。

Multiprocessing(多进程)
Windows NT 支持对称多处理,Windows NT 的工作站版本可以支持两个处理器,服务器版可以支持到4个。为支持多处理,操作系统需要特殊的同步机制。在单处理器系统中,通过禁用中断,临界区中的代码执行时不会被打断。这对于维护内核数据结构的完整性来说是必需的。在多处理器环境下,就不可能在所有的处理器上都禁用中断。在多处理环境中,Windows NT 使用自旋锁来保护内核数据结构。

注:多处理可分为对称的和非对称的。在非对称多处理中,有一个处理器为主处理器,其它的处理器都为从处理器。只有主处理器运行在内核模式,其它从处理器都只运行在用户线程。只要运行在用户线程的从处理器一调用系统服务,主处理器就接管此线程并执行所需的内核服务。调度程序,一个内核程序,之运行在主处理器上。因此,主处理扮演者调度员的角色,将用户模式线程分派给从处理器。很自然,与所有处理器都可在内核或用户模式运行的对称多处理相比,主处理器负担很重,系统不均衡。


International Language Support(国际化语言支持)
如今众多的 PC 用户都使用英语之外的其它语言。与这些用户能很好交互的关键就是使操作系统能支持用户们的语言。Windows NT 通过使用 Unicode 标准的字符集实现了这一目标。Unicode 标准规定了一个16位的字符集,而ASCII 使用的是8位字符集。 Unicode 的前256个字符的编码与 ASCII 的相同。这就为非拉丁语的语言留出了充足的空间。Win32 API 能接受 Unicode 和 ASCII 两种字符集,而 Windows NT 的内核则只能使用 Unicode。尽管应用程序程序员可以不去了解 Unicode,但驱动程序的开发者必须熟悉 Unicode,因为内核接口函数只接受 Unicode 字符串而且驱动的入口点都用的是 Unicode。

Windows NT 从 MACH 操作系统那里借用了核心体系,MACH 操作系统是在卡耐基梅隆大学开发的。MACH 操作系统的基本理念就是通过将复杂的操作系统功能交给用户级进程而将内核减至最小。这种客户机-服务器的操作系统体系还有另外一个目的:允许在同一操作系统上使用多种 APIs。通过在服务器进程中实现 APIs 就可以做到。

MACH 操作系统的内核提供了非常简单的一组接口函数。服务器进程使用这组接口函数实现出某种 API 来提供一组更复杂的接口函数。Windows NT 从 MACH 那里借用了这个理念。Windows NT 中的服务器进程被称作子系统。模块化和结构化的程序设计都是优秀软件管理的原则,NT 选择使用客户机-服务器的体系结构显示了它对这种原则的服从。Windows NT 本可以将所需的 APIs 在内核实现,也可以在内核上加上不同的层来实现不同的 APIs。出于维护性和扩展性的目的,NT 团队选择了子系统的办法。

Windows NT 中有两种子系统: integral subsystems 和 environment subsystems。Integral subsystems,如安全管理子系统,完成基本的操作系统任务。 Environment subsystems 则使得一台 Windows NT 机器能使用不同种类的 APIs。Windows NT 的子系统能支持以下的 APIs:

Win32 子系统。Win32 子系统提供 Win32 API。使用 Win32 API 的应用程序可以运行在微软 提供的所有平台上—

WOW 子系统。Windows on Windows (WOW) 子系统提供了对 16-bit Windows 应用程序的兼容,使得 Win16 的应用程序可以在 Windows NT 上运行。只要没有使用 Windows NT 不支持的未公开函数,这些应用程序都可以运行。

NTVDM 子系统。NT Virtual DOS Machine (NTVDM) 提供了一个基于文本的环境,DOS 程序可以在这个环境中运行。

OS/2 子系统。OS/2 子系统能运行 OS/2 应用程序。WOW、NTVDM 和 OS/2 都只能用在 Intel 平台上,因为他们都对应用程序提供二进制兼容性。而用于一种处理器的可执行文件或二进制文件就不能用在另一种处理器上,因为处理器间的机器指令格式不同。

POSIX 子系统。POSIX 子系统提供符合 POSIX 1003.1 标准的 API。

应用程序并不知道所调用的 API 是由相应的子系统处理的。这种隐藏是通过每种子系统各自的客户端 DLL 来实现的。这种 DLL 将 API 调用转换为本地过程调用(local procedure call,LPC)。本地过程调用类似于联网的 UNIX 上的远程过程调用(RPC)。使用 RPC,客户应用程序可以调用运行在网络上另一台机器上的服务器进程。 LPC 对运行在同一台计算机上的客户机与服务器进行了优化。


NT内核主要包含以下几个重要文件:
Ntoskrnl.exe(或者Ntkrnlpa.exe)  
HAL.Dll
NTDll.Dll
Win32k.Sys

NT内核的核心是NT EXECUTIVE。对应的文件是Ntoskrnl.exe。如果是机器是多处理器的,则是Ntkrnlpa.exe。非常可笑的是,这个文件可以直接删除,其后果就是重启后Windows无法启动,甚至连滚动条都看不到。该文件只有2MB左右的大小,但可谓是麻雀虽小五脏俱全,它作为整个Windows中最核心的部分,向外界提供了复杂的接口。

与之相辅相成的是HAL.Dll文件,即Hardware Abstraction Layer 硬件抽象层 。它直接与机器的硬件打交道,将硬件的差异对其之上的层隐藏起来。Windows NT 是一个有高可移植性的操作系统,运行在多种平台上。HAL.DLL 包含的代码向核心的其它部分隐藏了处理器和机器相关的细节。因此平台之间只有 HAL.DLL 不同,剩下的使用 HAL 接口的核心代码都有很高的可移植性。

NTDll.Dll模块。导出了大部分的Native API函数,提供了由用户态至内核态的切换的功能。做过Windows平台开发的人都知道,Windows API主要由Kernel32.Dll, User32.Dll, GDI32.Dll构成。其实对WindowsAPI的调用最终会被转接到NTDll。即所谓Native API,命名上基本上就是在原API前面加上Nt或者Zw(比如CreateFile就变成了NtCreateFile)。而Kernel32.Dll, User32.Dll, GDI32.Dll三个文件则组成了Win32子系统,它们本身不实现API,它导出的函数被称为stub 函数(尽管名称上看起来很迷惑人)

Win32K.sys模块。实现了Windows的图形处理部分。USER32 和 GDI32 使用系统调用接口来调用 WIN32K.SYS 中的服务。由于其工作与内核态,所以具有很高的性能,这也成就了Windows系统的强大的图形处理能力。









本文转自 kevx 51CTO博客,原文链接:http://blog.51cto.com/spinlock/174696,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
Windows
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
63 0
|
4月前
|
监控 安全 API
5.9 Windows驱动开发:内核InlineHook挂钩技术
在上一章`《内核LDE64引擎计算汇编长度》`中,`LyShark`教大家如何通过`LDE64`引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的`InlineHook`函数挂钩其实与应用层一致,都是使用`劫持执行流`并跳转到我们自己的函数上来做处理,唯一的不同的是内核`Hook`只针对`内核API`函数,但由于其身处在`最底层`所以一旦被挂钩其整个应用层都将会受到影响,这就直接决定了在内核层挂钩的效果是应用层无法比拟的,对于安全从业者来说学会使用内核挂钩也是很重要。
40 1
5.9 Windows驱动开发:内核InlineHook挂钩技术
|
4月前
|
监控 Windows
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
在笔者上一篇文章`《内核监视LoadImage映像回调》`中`LyShark`简单介绍了如何通过`PsSetLoadImageNotifyRoutine`函数注册回调来`监视驱动`模块的加载,注意我这里用的是`监视`而不是`监控`之所以是监视而不是监控那是因为`PsSetLoadImageNotifyRoutine`无法实现参数控制,而如果我们想要控制特定驱动的加载则需要自己做一些事情来实现,如下`LyShark`将解密如何实现屏蔽特定驱动的加载。
32 0
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
|
19天前
|
监控 安全 API
7.3 Windows驱动开发:内核监视LoadImage映像回调
在笔者上一篇文章`《内核注册并监控对象回调》`介绍了如何运用`ObRegisterCallbacks`注册`进程与线程`回调,并通过该回调实现了`拦截`指定进行运行的效果,本章`LyShark`将带大家继续探索一个新的回调注册函数,`PsSetLoadImageNotifyRoutine`常用于注册`LoadImage`映像监视,当有模块被系统加载时则可以第一时间获取到加载模块信息,需要注意的是该回调函数内无法进行拦截,如需要拦截则需写入返回指令这部分内容将在下一章进行讲解,本章将主要实现对模块的监视功能。
37 0
7.3 Windows驱动开发:内核监视LoadImage映像回调
|
4月前
|
监控 安全 API
7.2 Windows驱动开发:内核注册并监控对象回调
在笔者上一篇文章`《内核枚举进程与线程ObCall回调》`简单介绍了如何枚举系统中已经存在的`进程与线程`回调,本章`LyShark`将通过对象回调实现对进程线程的`句柄`监控,在内核中提供了`ObRegisterCallbacks`回调,使用这个内核`回调`函数,可注册一个`对象`回调,不过目前该函数`只能`监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。
30 0
7.2 Windows驱动开发:内核注册并监控对象回调
|
4月前
|
监控 安全 API
7.6 Windows驱动开发:内核监控FileObject文件回调
本篇文章与上一篇文章`《内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShark`将回调结构体`OB_OPERATION_REGISTRATION`中的`ObjectType`填充为了`PsProcessType`和`PsThreadType`格式从而实现监控进程与线程,本章我们需要将该结构填充为`IoFileObjectType`以此来实现对文件的监控,文件过滤驱动不仅仅可以用来监控文件的打开,还可以用它实现对文件的保护,一旦驱动加载则文件是不可被删除和改动的。
29 1
7.6 Windows驱动开发:内核监控FileObject文件回调
|
4月前
|
监控 安全 API
6.9 Windows驱动开发:内核枚举进线程ObCall回调
在笔者上一篇文章`《内核枚举Registry注册表回调》`中我们通过特征码定位实现了对注册表回调的枚举,本篇文章`LyShark`将教大家如何枚举系统中的`ProcessObCall`进程回调以及`ThreadObCall`线程回调,之所以放在一起来讲解是因为这两中回调在枚举是都需要使用通用结构体`_OB_CALLBACK`以及`_OBJECT_TYPE`所以放在一起来讲解最好不过。
45 1
6.9 Windows驱动开发:内核枚举进线程ObCall回调
|
4月前
|
监控 安全 API
6.8 Windows驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章`《内核枚举LoadImage映像回调》`中`LyShark`教大家实现了枚举系统回调中的`LoadImage`通知消息,本章将实现对`Registry`注册表通知消息的枚举,与`LoadImage`消息不同`Registry`消息不需要解密只要找到`CallbackListHead`消息回调链表头并解析为`_CM_NOTIFY_ENTRY`结构即可实现枚举。
54 1
6.8 Windows驱动开发:内核枚举Registry注册表回调
|
4月前
|
存储 API 开发者
6.7 Windows驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。
32 1
6.7 Windows驱动开发:内核枚举LoadImage映像回调
|
4月前
|
网络协议 API C++
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的`sfilter`文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使用过滤管理器`FilterManager`提供接口,由于提供了管理结构以及一系列管理API函数,所以枚举过滤驱动将变得十分容易。
52 1
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动