读书频道 > 系统 > windows > Windows内核原理与实现
6.5.6 非即插即用驱动程序
2013-05-20 08:55:41     我来说两句 
收藏    我要投稿   

本文所属图书 > Windows内核原理与实现

本书从操作系统原理的角度,详细解析了Windows如何实现现代操作系统的各个关键部件,包括进程、线程、物理内存和虚拟内存的管理,Windows中的同步和并发性支持,以及Windows的I/O模型。在介绍这些关键部件时,本...  立即去当当网订购

除了与设备关联的即插即用驱动程序,Windows 还支持非即插即用驱动程序和文件系统驱动程序。这一节我们讨论非即插即用驱动程序,这种驱动程序也称为内核扩展驱动程序,在Windows 驱动程序模型(WDM)出现以前的驱动程序均属于这一类,它们在Windows 2000/XP/Server 2003 及后续版本中仍然可以使用。但由于这一类驱动程序不支持WDM,所以,即插即用管理器和电源管理器无法管理它们,以及它们所创建的设备对象。在有些情况下,非即插即用驱动程序仍然是一个合适的选择,例如,本书前几章介绍的所有工具(以及后面6.7节将要介绍的IRPMon 工具)都使用了非即插即用驱动程序。

非即插即用驱动程序最主要的意义在于,让用户程序与内核之间多了一种通信方式,并且用户程序可以指示驱动程序做一些只有在内核中才能完成的任务,例如,访问系统地址空间中的数据,提供一种新的跨进程通信机制,或者访问内核提供的功能。当然,非即插即用驱动程序也可以驱动设备,直接与硬件打交道。不具备即插即用能力的硬件设备仍然可以通过这种驱动程序来工作。

这一类驱动程序的一种典型用法是,当软件需要内核中的功能时,应用程序通过服务控制管理器(SCM)来安装和加载驱动程序,然后通过I/O 管理器与驱动程序进行通信;当应用程序退出时,如不再需要该驱动程序则通过 SCM 动态地卸载。下面我们通过Windows DDK中提供的一个例子程序IOCTL 来说明这一过程。

IOCTL 例子包括两个程序:ioctlapp.exe 和sioctl.sys 。其中ioctlapp.exe 是一个命令行应用程序,该程序在启动时安装和加载驱动程序,并通过DeviceIoControl API 函数向驱动程序发送4 个不同类型的I/O 请求,分别为METHOD_IN_DIRECT、METHOD_ OUT_DIRECT、METHOD_NEITHER和METHOD_BUFFERED,关于这些I/O 请求类型,参见 6.6.3节的说明。Ioctlapp 程序在发送了这4 个请求以后,卸载驱动程序并退出。Sioctl.sys 是一个非即插即用驱动程序,它提供了初始化例程、卸载例程,以及 3 个分发例程,分别处理IRP_MJ_CREATE 、IRP_MJ_CLOSE 和IRP_MJ_DEVICE_CONTROL命令。它的初始化例程除了注册其他的例程以外,也调用 IoCreateDevice 函数创建一个设备对象,该设备对象的名称为“\Device\SIOCTL ”,而且它还调用IoCreateSymbolicLink函数来创建一个DOS 设备名称“\DosDevices\IoctlTest ”。因此,ioctlapp 程序可以通过CreateFile函数来打开一个指向此设备对象的文件对象,从而请求该设备对象的服务,相当于调用到该驱动程序的例程中。

现在我们来看ioctlapp 程序如何操纵 sioctl.sys 驱动程序。为了使用SCM的功能,ioctlapp 首先调用API 函数OpenSCManager ,以便连接到 SCM,并打开系统服务数据库。然后通过SCM中的以下服务来操纵sioctl.sys :

•  CreateService,创建一个 Windows 服务,将它安装到 SCM数据库中。CreateService 会在HKLM\System\CurrentControlSet\Services 下面创建一个子键,子键的名称等同于新建服务的名称,由参数来指定。CreateService 的参数较多,因为它必须指定新建服务的服务类型、启动类型、驱动程序路径等各种信息。这些信息都将保存在 SCM数据库中。

•  OpenService,打开一个已安装的服务。在参数中指定服务名称和访问方式。

•  StartService ,启动一个已通过 CreateService 或OpenService打开的服务。

•  ControlService,指示一个服务暂停(pause)、继续(continue )、停止(stop )或者向SCM报告其状态。

•  DeleteService,将指定的服务从 SCM数据库中删除。

应用程序通过句柄(其类型为SC_HANDLE )来管理所用到的服务,以及它与SCM之间的连接。当应用程序完成了SCM连接或者一个服务时,它调用CloseServiceHandle来结束相应的句柄。关于以上这些SCM API函数的用法,请参考ioctlapp 应用程序的代码或者Windows SDK中的相关文档。

从sioctl.sys 驱动程序的角度来看,当 SCM的StartService 服务被调用时,该驱动程序被加载到系统中。驱动程序的加载过程是通过NtLoadDriver 函数,进而由IopLoadDriver函数来完成的。驱动程序的初始化例程(即 DriverEntry 函数)是在 IopLoadDriver函数中被调用的,参见6.2.1节的介绍,这里不再赘述。驱动程序的卸载例程(SioctlUnloadDriver )是在IopLoadUnloadDriver 函数中被调用的,这发生在ioctlapp 应用程序调用ontrolService来停止服务之时。

通过这种方式创建的设备对象并没有参与到系统的设备树和设备节点中。然而,如果在系统引导时由即插即用管理器来加载一个非即插即用的驱动程序,那么,该驱动程序也会参与到设备树中。如果一个非即插即用的驱动程序被安装到系统中,并且它的启动类型设置为“引导-启动”或“系统-启动”,那么,在系统引导时,即插即用管理器会按照即插即用驱动程序来加载此驱动程序,并且为它建立一个设备节点插入到设备树中。这些设备节点直接附载在根节点的下面,其 PDO为驱动程序“\Driver\PnpManager ”创建的设备对象。由于被加载的驱动程序通常并未提供增加设备例程,因此这些设备节点中只有总线驱动程序创建的PDO ,而并不存在FDO 。在这种情况下,即插即用管理器加载并初始化驱动程序,但驱动程序并不会参与到设备节点中。这些驱动程序可以创建一个命名的设备对象,从而使应用程序可以通过名称来指定I/O 请求的目标。

非即插即用驱动程序也可以通过“添加硬件向导”来安装,在这种情况下.inf 文件是必需的。即插即用管理器会创建一个设备节点,并创建PDO ,其加载过程类似于引导时加载非即插即用驱动程序的情形,这里不再赘述。

最后简单小结一下以上关于Windows 设备驱动程序的讨论。本质上讲,Windows 的设备驱动程序是一个动态链接库,它的入口点是初始化例程,I/O 系统所要求的其他例程都是在初始化例程中指定的。在本节中,我们通过toaster 例子讨论了硬件设备的设备栈是如何构建起来的,以及过滤驱动程序如何参与其中。然而,本节并没有介绍驱动程序应该如何响应各种I/O 请求。关于如何编写驱动程序的例程来响应I/O 请求,请读者参考Windows DDK的文档说明,或者 Walter Oney的著作[WALTER]。另外,Windows DDK提供的丰富的例子展示了各种类型的硬件设备的驱动程序应如何实现。

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:6.5.5 过滤驱动程序的配置和加载
下一篇:Windows 8 使用详解
相关文章
图文推荐
3.4.4 进程生命期管
3.4.2 Windows应用商
3.4.1 Windows应用商
3.4 进程生命期管理
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站