windows驱动编程(二) windows系统整体框架详解

来源:互联网 发布:文科恋曲知乎 编辑:程序博客网 时间:2024/05/22 15:52

学习张帆的《windows驱动开发技术详解》,由此整理。。。感谢作者!

通过这篇文章能了解windows 的整体结构,明白驱动所处的位置和作用。


windows特性

(1)可移植性
windows操作系统为了实现在尽可能多的硬件平台上运行,引入了HAL(硬件抽象层)
(2)兼容性
为了实现windows系统不同版本之间的兼容性,保持了大多数的API统一且固定
(3)健壮性和可靠性
源自于分层的设计,配合每层的权限不同来实现。大致上分为用户模式和内核模式,用户模式具有最低的权限,对操作系统的操作仅仅限制于API的使用。(注意:权限是由CPU的特权分层来实现的,应用程序运行在Ring3层,拥有最低的权限,内核运行在Ring0层,拥有最大的权限。)API是操作系统提供给应用程序唯一的接口。当应用程序访问硬件设备是,必须向操作系统提出申请。操作系统会检查应用程序通过API提出的请求,并校验请求的参数是否合法,若非法参数,则返回一个错误码。
(4)可扩展性
可扩展性是指操作系统应该易于增加新的功能和支持新的硬件,并且对已有的代码影响最小。操作系统的结构中内核和执行体组件是分离的,内核只负责关于线程的调度工作。线程运行在自己的线程上下文中,线程上下文是指cpu寄存器的状态,例如:堆栈寄存器、指令寄存器、还包括线程ID,线程优先权、线程的本地存储等相关信息。
执行体组件是操作系统的一部分,例如:内存管理组件,进程管理组件,IO设备管理组件等这些统称为执行体组件。此组件按照模块化的方式设计,因此添加新功能和新设备时,增加新的组件即可。
(5)性能
由于分层的设计会影响系统的一些性能,在HAL层,功能调用都是通过宏来实现的。IO操作时基于异步设计的、是基于多线程多进程的操作系统。


windows系统分层框架


(1)一条粗线将windows系统分割为内核模式和用户模式。在用户模式下,应用程序调用各自子系统的API接口,子系统是为了更好的兼容16位windows系统和移植其他系统的程序设计的。包括win32子系统,OS/2子系统、POSIX子系统。其中win32子系统是windows最主要的子系统,其他子系统都是通过win32子系统的调用来实现的。
(2)win32子系统讲API函数转化为Native API函数,Native API穿过的用户模式和内核模式的界限,到达了内核模式。系统服务函数通过IO管理器讲消息传递给驱动程序。
在内核模式下,执行体组件提供了大量的内核函数供驱动程序使用。
(3)大部分的win32API都是通过Native API实现的,NativeAPI一般都是在win32 API上加上Nt字母。添加一层Native API是为了考虑版本的兼容性。作为应用程序的开发者,只需要了解win32的API接口,而不用关心Native API的变化,这种机制可以让windows NT上的程序直接在更高版本上的windows上运行,而不用重新编译。
(4)Native API从用户模式穿越进入内核模式,调用系统服务。进入内核是通过软中断实现的,软中断讲不通API的参数和系统服务号一起带进内核模式。在系统服务组件中,有一个系统描述符表(System service descriptor table),由系统服务号为索引,在表中查到对应系统服务函数的函数地址。系统服务函数和Native API有着相同的名字,但要注意是不同的函数。
在系统服务函数的调用中,会检验参数的合法性,这也是操作系统的最后一道屏障,以后的任何操作,操作系统不会再做任何检查。任何错误都会导致系统的崩溃。

(5)windows的执行体组件位于Ntoskrnl.exe的上层,而内核位于Ntoskrnl.exe的下层。(ntoskrnl.exe 是 Windows 操作系统的一个重要进程文件,在系统经过预启动和启动阶段后进入内核调用阶段时由 Ntldr 调用 ntoskrnl.exe, 在 Windows XP 系统中 ntoskrnl.exe 存储了启动 logo 画面。 调用 ntoskrnl.exe 文件时将由 ntdetect.com 收集的硬件信息传递给它,同时被调用的还有 hal.dll 文件。ntoskrnl.exe 是保护性的进程,在你的计算机反复启动的情况下出现。在正常情况下,在任务管理器是以"System"的名字出现的)执行体组件是内核模式下的一组服务函数,他们都位于ntoskrnl.exe中。执行体组件又可细分为以下组件:
(a)对象管理组件
windows操作系统提供的所有服务几乎都是以对象的形式存在,类似于OOP中的对象概念,虽然windows操作系统不是用面向对象语言开发的,但借鉴了很多的面向对象的思想。
对象管理器程序就是创建、管理、回收这些对象的组件。在驱动开发中涉及到的对象例如:驱动程序对象、设备对象等等。
(b)进程管理程序
负责创建和终止进程,线程的调度由内核负责的。进程管理程序依赖其他执行体组件,例如:对象管理程序,虚拟内存管理程序。(进程是一个容器,拥有一个或多个线程。每个进程维护一个专门的地址空间和安全身份)
(c)虚拟内存管理程序
在CPU的内存管理单元(MMU)的协助下,通过某种映射讲物理内存和一部分主存关联起来(原文为和虚拟内存关联起来)。每个进程拥有4GB的虚拟内存。每个进程观察到的虚拟内存是完全不同的,这是因为每个进程的物理内存到虚拟内存的映射是不同的。这样保证进程之间不会相互干预。在4GB的虚拟内存空间中,0-0x7FFFFFFF规定为用户模式的地址,用户模式下的程序只能访问到这段虚拟内存,0x80000000-0xFFFFFFFF规定为内核模式下的程序访问。
另外,windows规定所有进程的内核模式下的虚拟内存的映射方式完全一样。这样在每个经常中,顶端2GB的内核模式地址的数据是完全一致的。如下图所示:


  (d)IO管理器
负责发起IO请求,并管理这些请求。目标是使来自于用户模式的IO请求独立于设备。对IO的读写操作都统一为IRP(IO request package)的请求形式。IRP中包含了操作设备的重要数据。例如:是读还是写,读多少字节,写多少字节、是直接读到用户模式,还是先读到系统缓冲区再读到用户进程中等等。
IRP被传递到具体的设备驱动中,驱动设备负责“完成”这些IRP,并将完成的状态返回到用户模式下的应用程序。
IO管理器担任着用户模式代码和设备驱动程序之间的接口。

(e)配置管理程序
使用注册表保存和记录计算机软、硬件的配置信息,设备驱动程序根据注册表中的信息进行加载。
驱动程序还可从注册表中读取参数,提高了驱动程序的灵活性。

(6)驱动程序,学习的重点
IO管理器接受应用程序的请求后,创建相应的IRP,并传至驱动程序进行处理,几种处理方法如下:
(a)根据IRP的请求,直接操作具体硬件,完成此IRP,并返回、
(b)将此IRP请求,转发到更底层的驱动中,并等待底层驱动的返回。
(c)接受到IRP请求后,不急于完成。而是分配新的IRP发到其他的驱动程序中,并等待返回。
注意:驱动程序处理IRP,一般是将这几种操作结合起来。


(7)内核,操作系统的心脏。相比执行器组件非常小,内核为执行器组件提供最基本的支持,负责线程的调度,通过自旋锁(spin Lock)提供对多cpu同步支持,提供中断处理。
内核的功能:
对内核对象的支持
对线程的调度
对多处理器同步的支持
中断处理函数支持
对错误陷阱的支持
对其他硬件特殊功能的支持
windows内核执行在最高的特权智商,他被设计成可以并行的运行在多个处理器上。

内核调度线程是原语操作,但可以被更高的中断请求级别(IRQL)所打断

(8)硬件抽象层

(9)windows和微内核
单一内核是指将操作系统的所有核心组件在内核中实现,linux就是如此,优点就是速度快。微内核就是讲操作系统的核心和组要组件分割开,他们运行在独立的进程中,都有自己的私有的地址空间。优点就是耦合性小。

windows讲负责对窗口消息分发处理的Use32.dll和负责窗口图形操作的GDI32.dll的代码放到了内核模式下的win32k.sys内。同时也保留了用户模式下原有的dll。

(10)总结:从应用程序到驱动程序
PC上的设备千差万别,为了统一接口,讲所有的设备以普通文件看待。即都用操作文件的方法来操作设备。
对应的win32 API如下:


下图是说明,win32 API如何一步一步的对设备驱动程序进行操作的:


以CreateFile为例:
(a)首先调用CreateFile API,此API是由win32子系统的三大模块中的Kernel32.dll实现的。CreateFile调用Ntdll.dll中的NtCreateFile函数,其中NtCreateFile是未文档化的函数,程序员最好不要使用。
(b)NtCreateFile的作用是通过软中断的方式,穿越用户模式的边界,进入到内核模式。
(c)进入内核以后,会调用系统的服务函数,这里会调用同名的系统服务函数NtCreateFile(同名,但一个在用户模式,一个在内核模式)。
(d)NtcreateFile系统函数调用通过IO管理器创建IRP并传输到设备的驱动程序中。IRP是输入输出包,是驱动程序开发中的重要的数据结构。程序的运行完全是靠IRP驱动的。可以理解为是一个消息。

这个复杂的过程,经过了多个层次的交互,只是为了执行一个读写端口的操作.....


------2013-10-28 15:43 SWYY


原创粉丝点击