2022年驱动开发学习笔记 .pdf

上传人:Q****o 文档编号:28024532 上传时间:2022-07-26 格式:PDF 页数:14 大小:141.65KB
返回 下载 相关 举报
2022年驱动开发学习笔记 .pdf_第1页
第1页 / 共14页
2022年驱动开发学习笔记 .pdf_第2页
第2页 / 共14页
点击查看更多>>
资源描述

《2022年驱动开发学习笔记 .pdf》由会员分享,可在线阅读,更多相关《2022年驱动开发学习笔记 .pdf(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、1、三种类型的 WDM 驱动程序总线驱动程序 (bus driver) 功能驱动程序 (function driver) 过滤驱动程序 (filter driver) 2、其他分类方法类驱动程序 (class driver) 端口驱动程序 (port driver) 小端口驱动程序 (miniort driver) 3、驱动程序对象 (DRIVER_OBJECT)主要成员DeviceObject: 指向一个设备对相链表,每个设备对象代表一个设备。DriverExtension: 一个结构体 , 该结构只有 AddDevice 成员可以直接访问。DriverStartIo: 指向驱动程序中处理I

2、/O 请求的函数。DriverUnload: 指向驱动程序中的清除函数。MajorFunction: 为一个函数指针表 , 指向存在于驱动程序中的各个IRP 处理函数, 它定义了 I/O 请求如何进入驱动程序。4、设备对象 (DEVICE_OBJECT)主要成员DriverObject: 指向与该设备对象相关的驱动程序对象。过滤驱动程序有时需要用这个指针来寻找被过滤设备的驱动程序对象。CurrentIrp: 指向最近发往驱动程序StartIo 函数的 I/O 请求包。Flags: 包含一组标志位DO_BUFFERED_IO: 读写操作使用缓冲方式(系统复制缓冲区 )访问用户模式数据DO_EXC

3、LUSIVE: 一次只允许一个线程打开设备句柄DO_DIRECT_IO: 读写操作使用直接方式 (内存描述符表 )访问用户模式数据DO_DEVICE_INITIALIZING: 设备对象正在初始化DO_POWER_PAGABLE: 必 须 在PASSIVE_LEVEL级 上 处 理IRP_MJ_PNP请求DO_POWER_INRUSH: 设备上电期间需要大电流Characteristics: 包含另一组标志位,描述设备的可选特征FILE_REMOVABLE_MEDIA: 可更换媒介设备FILE_READ_ONL Y_DEVICE: 只读设备FILE_FLOPPY_DISKETTE: 软盘驱动器

4、设备FILE_WRITE_ONCE_MDEIA: 只写一次设备FILE_REMOTE_DEVICE: 通过网络连接访问的设备FILE_DEVICE_IS_MOUNTED: 物理媒介已在设备中FILE_DEVICE_SECURE_OPEN: 在打开操作中检查设备对象的安全属性DeviceType: 一个枚举常量,描述设备类型。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 14 页 - - - - - - - - - FILE_DEVICE_PRINTER: 打印机FILE

5、_DEVICE_SCANNER: 扫描仪. FILE_DEVICE_UNKNOWN: 未知设备5、驱动程序对象与设备对象的关系一 方面 , 驱 动 程序 对 象通 常 有 多 个与它 相关 的设 备对 象,因 此 它利 用DeviceObject指针指向一个设备对象列表,该列表表示驱动程序可以控制的物理设备。另一方面 , 设备对象反过来指向它自己的驱动程序对象, 这样 I/O管理器就知道在接收一个 I/O 请求时应该调用哪个驱动程序。 每个功能码都对应一个驱动程序的入口点。6、I/O 请求包 (IRP) IRP 是 I/O 系统用来存储处理I/O 请求所需信息的地方 , I/O 管理器在 IR

6、P 中保存一个指向调用者文件对象的指针。从编程的角度看, IRP 是 I/O 管理器在响应一个 I/O 请求时从非分页系统内存中分配的一块可变大小的数据结构内存, I/O管理器每收到一个来自用户的请求就创建一个该结构,并将其作为参数传给驱动程序的 DispatchXxx、StartIo 等例程。该结构中存放有请求的类型、用户缓冲区的首地址、用户请求数据的长度等信息。驱动程序处理完这个请求后, 也在该结构中添加处理结果的有关信息, 然后调用 IoCompleteRequest 将其返回给 I/O 管理器, 用户程序的请求随即返回。每个 IRP 可以被看成由两部分组成: 固定部分 和一个 I/O

7、堆栈。 IRP 的固定部分包含关于请求的信息 , I/O 堆栈则包含一系列I/O 堆栈单元 (I/O Stack location), 单元的数目应与驱动程序堆栈中处理这一请求的驱动程序数目相同, 每个单元对应一个将处理该IRP 的驱动程序。IRP 固定部分的域MdlAddress(Memory Descriptor List, MDL): 指向一个 内存描述表 。 当驱动程序使用 直接 I/O 时, MDL 用来描述一个与该请求相关联的用户模式缓冲区AssociatedIrp: 该域是一个三指针联合, 其中与 WDM 驱动程序相关的指针是 AssociatedIrp.SystemBuffer

8、。 如果设备执行缓冲I/O, 则 SystemBuffer 指针指向系统空间缓冲区 , 否则为 NULL 。RequestorMode: 取值为一个枚举常量UserMode或 KernelMode, 指定请求初始化的模式为用户模式还是核心模式。驱动程序有时需要查看这个值来决定是否需要信任某些参数Cancel: 该域为 BOOLEAN 类型。如果为 TRUE, 则表明 IoCancelIrp 已被调用, 该函数用于取消这个请求。如果为FALSE, 则表明没有调用IoCancelIrp函数CancelIrql: 一个 IRQL(I/O Request Query Level)值, 表明那个专用的取

9、消自旋锁是在这个 IRQL 上获取的。当驱动程序在取消例程中释放自旋锁时应该参名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 14 页 - - - - - - - - - 考这个域CancelRoutine: 指 向 驱 动 程 序 取 消 例 程 的 地 址 。 应 该 使 用IoSetCancelRoutine函数设置 CancelRoutine域而不是直接修改该域IRP 堆栈单元中的域任何内核模式程序在创建一个IRP 时, 同时还创建了一个与之关联的I/O堆栈。堆栈

10、中的I/O 堆栈单元由 IO_STACK_LOCA TION 结构定义 , 每个堆栈单元都对应一个将处理的IRP 的驱动程序。为了在一个给定的IRP 中确定当前的IRP I/O 堆栈单元 , 驱动程序可以调用IoGetCurrentIrpStackLocation函数, 该函数返回当前 I/O 堆栈单元的指针。MajorFunction: 该 IRP的主要功能代码 , 它指出所要执行的 I/O 操作类型。例如: 主功能代码 IRP_MJ_READ 表示通过 Win32 API 函数 CreateFile发送的请求。主功能代码与驱动程序对像的MajorFunction 表中的某个分发函数指针相对

11、应。MinorFunction: 该 IRP 的副功能代码 , 它进一步指出该 IRP 属于哪个主功能 类 。 例 如 : IRP_MJ_PNP请 求 有 十 几 个 副 功 能 代 码 , 包 括IRP_MN_START_DEVICE 、IRP_MN_REMOVE_DEVICE等。DeviceObject: 指向该堆栈单元对应的设备对象地址, 该域由 IoCallDriver函数负责填写。FileObject: 指向与一个 I/O 请求有关的文件对象地址。I/O 功能代码IRP_MJ_CREATE: 打开设备CreateFile IRP_MJ_CLEANUP: 在关闭设备时 , 取消挂起的

12、I/O 请求CloseHandle IRP_MJ_CLOSE: 关闭设备CloseHandle IRP_MJ_READ: 从设备获得数据ReadFile IRP_MJ_WRITE: 向设备发送数据WriteFile IRP_MJ_DEVICE_CONTROL: 对用户模式或内核模式客户可用的控制操作DeviceControl IRP_MJ_INTERNAL_DEVICE_CONTROL: 只对内核模式客户程序可用的控制操作没有对应的 Win32 API IRP_MJ_QUERY_INFORMA TION: 得到文件的长度GetFileLength IRP_MJ_SET_INFORMATION:

13、 设置文件的长度SetFileLength IRP_MJ_FLUSH_BUFFERS: 写 输 出 缓 冲 区 或 丢 弃 输 入 缓 冲 区FlushFileBuffers FlushConsoleInputBuffer PureComm IRP_MJ_SHUTDOWN: 系统关闭InitialSystemShutdown 7、单层驱动程序的I/O 请求I/O 请求经过子系统DLL 子系统 DLL 调用 I/O 管理器的 NtWriteFile 服务I/O 管理器分配一个描述该请求的IRP, 并通过调用 IoCallDriver 函数向驱动程序 (这里指设备驱动程序 )发送请求驱动程序将 I

14、RP 中的数据传输到设备并启动I/O 操作名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 14 页 - - - - - - - - - 通过中断 CPU, 驱动程序发信号进行I/O 完成操作在设备完成操作并且中断CPU 时, 设备驱动程序服务于中断驱动程序调用IoCompleteRequest函数表明它已经处理完IRP 请求, 接管I/O 管理器完成 I/O 请求驱动程序可用的内核态例程:Ex. 执行支持Hal. 硬件抽象层 (仅 NT/Windows 2000) Io.

15、 I/O 管理器 (包括即插即用例程 ) Ke. 内核Mm. 内存管理器Ob. 对象管理器Po. 电源管理Ps. 进程结构Rtl. 运行时库Se. 安全引用监视Zw. 其他例程总线驱动程序和类特定的例程: BatteryClass. 小类驱动程序的电池类例程Hid. 人工输入设备 (HID) 例程Pc. 用于小端口驱动程序的SCSI Tape类例程Usb. 用于 USB 客户驱动程序的通用串行总线驱动程序接口例程IRP_MJ_CREATE 创建或打开设备文件IRP_MJ_CLOSE 关闭句柄IRP_MJ_READ 读IRP_MJ_WRITE 写IRP_MJ_CLEANUP 取消文件句柄上的任何

16、等待的IRP IRP_MJ_DEVICE_CONTROL 设备 I/O 控制IRP_MJ_INTERNAL_DEVICE_CONTROL 来自高层驱动程序的I/O 控制IRP_MJ_SYSTEM_CONTROL WMI IRP_MJ_POWER 电源管理请求IRP_MJ_PNP 即插即用消息IRP_MJ_SHUTDOWN 关闭通知UNICODE_STRING 结构定义:typedef struct _UNICODE_STRING USHORT Length; USHORT MaximumLength; PWSTR Buffer; UNICODE_STRING, *PUNICODE_STRING

17、; Buffer 域指向一个宽 16 位字符 (双字节)缓冲区,该字符串通常不是NULL 终止名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 14 页 - - - - - - - - - 的,而是由 Length域指定字符串的当前大小(字符数)UNICODE_STRING 函数:RtlAnsiStringToUnicodeString: 把 ANSI 字符串转换成Unicode字符串,可选地分配一个缓冲区RtlAppendUnicodeStringToString: 把一

18、个 Unicode 字符串追加到另一个Unicode字符串,直到目标缓冲区的最大长度RtlAppendUnicodeToString: 追加一个宽字符串到Unicode 字符串,直到目标缓冲区的最大长度RtlCompareUnicodeString: 比较两个 Unicode字符串,可选择不区分大小写RtlCopyUnicodeString: 把一个 Unicode 字符串复制到另一个Unicode 字符串,直到目标缓冲区的最大长度RtlEqualUnicodeString: 如果两个 Unicode 字符串相等, 返回 TRUE,可选择不区分大小写RtlInitUnicodeString :

19、 设置 Unicode 字符串缓冲区指向指定的宽字符串,并设置长度域为匹配值RtlIntegerToUnicodeString: 把 ULong 值转换成指定基的Unicode 字符串,字符串缓冲区必须提前初始化RtlPrefixUnicodeString: 检查一个 Unicode字符串是否是另一个Unicode字符串的前缀,可选择不区分大小写RtlUnicodeStringToAnsiString: 把 Unicode 字符串转换成ANSI,如果分配目标ANSI 缓冲区,最终使用RtlFreeAnsiString 释放它RtlUnicodeStringToInteger: 把 Unicod

20、e 字符串转换成一个整数RtlUpcaseUnicodeString: 把 Unicode 字符串转换成大写,可选地分配缓冲区IoCreateDevice函数:NTSTATUS IoCreateDevice IRQL = PASSIVE_LEVEL IN PDRIVER_OBJECT DriverObject 驱动程序对象IN ULONG DeviceExtensionSize 要求的设备扩展的大小IN PUNICODE_STRING DeviceName 设备名称,或者 NULL IN DEVICE_TYPE DeviceType 设备的类型, 标准头文件 WDM.H 或 NTDDK.H中列

21、出的 FILE_DEVICE_XXX值之一IN ULONG DeviceCharacteristics 各种常量用 OR组合在一起,指示可删除介质、只读等IN BOOLEAN Exclusive 如果一次只有一个线程可以访问该设备,为TRUE OUT PDEVICE_OBJECT* DeviceObject 返回的设备对象名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 14 页 - - - - - - - - - IoRegisterDeviceInterface函数NT

22、STATUS IoRegisterDeviceInterface IRQL = PASSIVE_LEVEL 参数描述IN PDEVICE_OBJECT PhysicalDeviceObject 设备 PDO IN CONST GUID* InterfaceClassGuid 被注册的 GUID IN PUNICODE_STRING ReferenceString 通常是NULL, 引用字符串或成为接口名称的一部分,所以可以用于区分同一设备的不同接口OUT PUNICODE_STRING SymbolicLinkName 输出接口符号连接名,完成使用时,不要忘记使用RtlFreeUnicodeS

23、tring释放这个 Unicode 字符串IoRegisterDeviceInterface函数NTSTATUS IoRegisterDeviceInterface 参数描述IN PDEVICE_OBJECT PhysicalDeviceObject 设备 PDO IN CONST GUID* InterfaceClassGuid 被注册的 GUID IN PUNICODE_STRING ReferenceString 通常是 NULL ,引用字符串成为接口名称的一部分,所以可以用于区分统一设备的不同接口OUT PUNICODE_STRING SymbolicLinkName 输出接口符号链接

24、名。完成使用时,不要忘记使用RtlFreeUnicodeString释放这个 Unicode 字符串设备名:符号链接:这个名字向内核标识设备,而不是向Win32 标识设备。根据约定,内核设备名从 0 开始编号,而符号链接名从 1 开始编号。用 IoCreateSymbolicLink创建。设备接口:驱动程序使用设备接口使它的设备对Win32 程序可见,主要思想是:每个设备使一个定义的应用程序编程接口(API)可用,全局唯一标识符(GUID) 用于标识这个接口。操作系统版本的确定:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名

25、师精心整理 - - - - - - - 第 6 页,共 14 页 - - - - - - - - - 可以使用注册表设置在运行时确定是否正运行Windows 98。在 NT 和 Windows 2000中,可用以下注册表值:HKLMSystemCurrentControlSetControlProductOptionsProductType。对Workstation/Professional Windows版本, 这个值是 WinNT ; 对于 Server/Enterprise版本,这个值是 LanmanNT或者是 ServerNT。在 Windows 98 中,这个注册表值不可用。驱动程序

26、出错的方式:1、操作系统崩溃 ( 访问不存在的内存,在DISPATCH_LEVEL 或以上的中断级访问分页内存) 2、内核转储3、驱动程序不启动4、挂起5、遗漏资源6、时间依赖性检查版本:#if DGB DbgPrint( Wdm1 checked ); #else DbgPrint( Wdm1 free ); 可重入性:就是说它可以被同时 调用处理连个不同的IRP。在多处理器的Windows 2000 系统中,一个处理器可能是用一个IRP 调用 Wdm1Read ,另一个CPU 上的第二个进程也同时使用另一个IRP调用 Wdm1Read。使一个例程是可重入的第一个技术是使用局部变量,Debu

27、gPrint格式说明符符号格式说明符类型%c ANSI 字符char %C 宽字符wchar_t %d,%i 十进制有符号整数int %D 十进制 _int64 _int64 %I IRP 主功能代码和次功能代码PIRP %L 十六进制的 LARGE_INTEGER LARGE_INTEGER %s NULL 终止的 ANSI 字符串char* %S NULL 终止的宽字符串wchar_t* %T UNICODE_STRING PUNICODE_STRING %u 十进制的 ULONG ULONG 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - -

28、 - - - - 名师精心整理 - - - - - - - 第 7 页,共 14 页 - - - - - - - - - %x 十六进制的 ULONG ULONG 一些 IRP 首部结构域域描述IO_STATUS_BLOCK IoStatus IRP 的完成状态PVOID AssociatedIrp.SystemBuffer 系统空间缓冲区 (用于缓冲 I/O) BOOLEAN Cancel 设置 IRP 是否已经被取消ULONG Flags IRP 标志CTL_CODE 宏参数参数描述DeviceType 指定 IoCreateDevice的 FILE_DEVICE_XXX值ControlC

29、ode IOCTL 功能代码0 x000 0 x7FF 为 Microsoft 保留0 x800 0 xFFF是私有代码TransferType METHOD_BUFFERED METHOD_IN_DIRECT METHOD_OUT_DIRECT METHOD_OUT_DIRECT METHOD_NEITHER RequiredAccess FILE_ANY_ACCESS FILE_READ_DA TA FILE_WRITE_DA TA FILE_READ_DA TA | FILE_WRITE_DA TA 缓冲 I/O:驱动程序可以使用两个主要的方法访问用户缓冲区,这两个方法是缓冲 I/O名师

30、资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 14 页 - - - - - - - - - 和 直 接I/O 。 在 创 建 设 备 时 , 必 须 设 置 新 设 备 对 象 的Flags 域 中 的DO_BUFFERED_IO 位来使用缓冲I/O,或设置 DO_DIRECT_IO 位来使用直接I/O。如果使用缓冲 I/O,内核使用户的缓冲区在某个非分页内存 中可用,并在 IRP 首部的 AssociatedIrp.SystemBuffer域中存储合适的指针。 在驱动程序

31、中简单地读或写这个内存。这个技术是驱动程序开发者最容易使用的一个技术。但是, 它总体上速度要慢些,因为操作系统通常必须要把用户缓冲区复制到非分页内存或者从非分页内存复制出来。直接 I/O:使用内存描述符列表(MDL) 速度要快些,但这仅可用于执行直接内存访问(DMA) 的硬件。用户缓冲区的MDL 放在 IRP 首部的 MdlAddress 域中。DeviceIoControl 缓冲区自旋锁 :内核自旋锁在BufferLock 提供这个保护。自旋锁可以用在代码需要短时访问某种资源的地方。KSPIN_LOCK BufferLock; / 声明一个自旋锁对象KeInitializeSpinLock(

32、 &BufferLock ); / 初始化KeAcquireSpinLock( &BufferLock, XXX ); / 获得自旋锁KeReleaseSpinLock( &BufferLock, XXX ); / 释放自旋锁自旋(spin)是指 KeAcquireSpinLock 不断进行监视。 由于这个原因, 我们只能持有一个自旋锁很短的时间。DDK 建议不要持有自旋锁超过25 微秒。我们在 KeAcquireSpinLock 的调用中,必须提供一个指向KIRQL 变量的指针,这个变量存储在提升到DISPATCH_LEVEL 之前的原始IRQL 级。在必要时,KeReleaseSpinLo

33、ck的调用降低 IRQL。 如果肯定代码在 DISPATCH_LEVEL IRQL运行,可以使用KeAcquireSpinLockAtDpcLevel和KeReleaseSpinLockFromDpcLevel例程得到更好的性能。在持有一个自旋锁时, 不要访问分页代码或数据, 因为系统几乎肯定会崩溃。 在持有一个自旋锁时,千万不要退出主分发例程。设备驱动程序工作的次序:1) 一个标准总线驱动程序检测何时添加一个设备2) 设备标识符用于发现驱动程序。3) 驱动程序被装入,并告诉它添加了一个新设备。4) 进一步的消息告诉用户使用了哪些资源。5) 然后驱动程序与设备通信,这可能要使用一个标准驱动程序

34、的服务来实现。当一个设备拔出时, Windows检测到这个事件, 并告诉驱动程序该设备已经不存在。即插即用设备检测名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 14 页 - - - - - - - - - 目标在加电时检测全部设备装入最合适的驱动程序为每个驱动程序分配资源对于可热插拔的设备,在添加或删除设备时处理解决方案提供枚举器总线驱动程序, 发现新设备, 并检测何时添加或删除设备每个设备提供标识符,用于发现最合适的驱动程序总线驱动程序或 INF 文件提供设备的资源分

35、配提供仲裁器确定给每个设备分配哪些资源发送消息指示设备事件缺点正在运行的设备可能必须停止,这样才可以重新分配它们资源过滤驱动程序只是在设备第一次安装时安装,所以在设备栈构造后就不能插入过滤驱动程序。单一驱动程序和分层驱动程序:键盘驱动程序为单一驱动程序,因为它接管处理键盘要求的所有处理 (即它不是用其它的驱动程序)。相反,USB 驱动程序使用分层方法,为了使用USB 键盘,键盘驱动程序需要使用USB 类驱动程序的服务。即插即用次功能代码常用 PnP IRP 功能IRP_MN_START_DEVICE 分配资源并启动一个设备IRP_MN_QUERY_REMOVE_DEVICE 询问一个设备是否可

36、以被删除IRP_MN_CANCEL_REMOVE_DEVICE 取消查询删除请求IRP_MN_REMOVE_DEVICE 设备被拔出或卸下取消资源分配并删除设备IRP_MN_SURPRISE_REMOVAL( 仅 Windows 2000) 用户在意外的情况下拔出设备IRP_MN_QUERY_STOP_DEVICE 取消查询停止请求IRP_MN_STOP_DEVICE 停止设备进行资源重新分配不常用 PnP IRP IRP_MN_QUERY_DEVICE_RELA TIONS 查询有特定特征的PDO IRP_MN_QUERY_INTERFACE 让驱动程序导出直接调用接口IRP_MN_QUER

37、Y_CAPABILITIES 查询设备功能(如它是否可以被锁定货弹出) IRP_MN_QUERY_RESOURCES 取出设备的引导配置资源IRP_MN_QUERY_RESOURCE_REQUIREMENTS 查询设备的资源要求名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 14 页 - - - - - - - - - IRP_MN_QUERY_DEVICE_TEXT 得到设备的描述或位置字符串IRP_MN_FILTER_RESOURCE_REQUIREMENTS 让过

38、滤驱动程序和功能驱动程序过滤设备的资源要求IRP_MN_READ_CONFIG 读配置空间信息IRP_MN_WRITE_CONFIG 设置配置空间信息IRP_MN_EJECT 从设备槽弹出设备IRP_MN_SET_LOCK 设置设备锁定状态IRP_MN_QUERY_ID 设置设备的硬件、兼容性和实例ID IRP_MN_QUERY_PNP_DEVICE_STATE 设置设备状态位映射中的位IRP_MN_QUERY_BUS_INFORMATION 得到副总线的类型和实例号IRP_MN_DEVICE_USAGE_NOTIFICA TION 通知设备是在分页文件、休眠文件还是崩溃转储文件的路径中IRP

39、_MN_QUERY_LEGACY_BUS_INFORMATION 返 回 遗 留 总 线 信 息 (仅Windows 2000) 当一个设 备被添 加到系 统时, Windows 查找正 确的驱 动程序 ,并调 用它的DriverEntry 例程,告诉它添加了一个设备。 就是这个时候, 驱动程序创建他自己的的设备对象,即功能设备对象(FDO)。但是驱动程序还不试图访问它的设备硬件。在处理的过程中,驱动程序收到一个IRP_MN_START_DEVICE IRP,包括设备被分配的资源的信息,然后他开始与设备硬件进行合适的对话。如果一个设备要被拔出, Windows 使用 IRP_MN_REMOVE

40、_DEVICE IRP查询驱动 程 序 设 备 是 否 可 以 被 删 除 。 如 果 驱 动 程 序 同 意 , 则 发 送 一 个IRP_MN_REMOVE_DEVICE IRP 删除设备。如果驱动程序不希望设备被删除(如它 正 处 于 一 个 长 的 传 输 过 程 中 ) , 它 将 拒 绝 删 除 请 求 , 然 后 发 送IRP_MN_CANCEL_REMOVE_DEVICE IRP ,使它回到开始的状态。如 果 用 户 偶 然 拔 出 一 个 设 备 , 在Windows 98 中 给 驱 动 程 序 发 送 一 个IRP_MN_REMOVE_DEVICE IRP,在Window

41、s 2000中发送IRP_MN_SUPPRISE_REMOVE IRP。我们必须处理好中断的传输。在删除请求的响应中, IRP_MN_QUERY_STOP_DEVICE IRP 询问是否可以停止设备。如果可以停止设备,则发出IRP_MN_STOP_DEVICE IRP ,使设备进入停止状态。如果不能停止设备,则发出IRP_MN_CANCEL_STOP_DEVICE IRP,使设备回 到启动 状态 。当设 备停止 时,驱 动程序 不能 访问它 的设备 ,一个IRP_MN_START_DEVICE IRP 通知驱动程序设备的新资源并再次启动设备。注意:当设备处于停止状态或等待状态时可能会收到删除设

42、备消息。PnP配置管理器为驱动程序将基本的系统资源分类为:I/O 端口、内存地址、DMA通道和中断。当 Windows 启动时,它并不知道哪些设备连接到计算机上。它可以发现自己的一些基本信息,如有多少内存,但是如何发现其他的信息呢?Windows 使用驱动程序枚举可用的硬件。枚举是指查找并列出任何可用的设备,名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 14 页 - - - - - - - - - 然后使用仲裁器调整所有的资源要求。对每个设备插找合适的驱动程序,然后告

43、诉这些驱动程序使用哪些资源,并运行这些驱动程序。查找根设备 |_ 串行设备| |查找|_ 键盘|查找查找查找|_ PCI总线_ PnP ISA 总线 _ 声卡| | |查找查找|_ USB 总线 _ USB 键盘| | | 查找|_ USB 打印机有两类电路可以用于PC 到物理 USB总线的接口: 开放主机控制接口 (OpenHCI)和通用主 机控 制器接 口 (UHCI) 。Windows 选择 OpenHCI.sys 驱动程 序或者UHCI.sys 驱动程序作为到这些电路接口的驱动程序层。为一个设备服务的主驱动程序称为功能驱动程序。安装INF 文件可能指定多个功能驱动程序放在一个设备栈中。

44、每个功能驱动程序或过滤驱动程序中的AddDevice 例程在创建新的设备栈时调用。对每个 AddDevice 例程传递一个指向相同总线驱动程序PDO 的指针,然后AddDevice 创建一个 FDO,挂接到该设备栈。AddDevice 例程的调用顺序确定设备栈中驱动程序的顺序。 这样,设备栈自底向上构造。 类似地, 当一个设备被删除时,设备栈通过先删除最上面的驱动程序来析构。PDO 作为这个设备栈的固定点,因为设备栈中的每个驱动程序有相同的PDO 指针。USB 键盘设备栈驱动程序设备栈HID 键盘驱动程序HID 键盘设备 FDO HID 类设备 FDO PDO(由 USB 集线器总线驱动程序创

45、建) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 14 页 - - - - - - - - - USB 集线器USB 集线器设备 FDO PDO(由 USB 主机控制器总线驱动程序创建) USB 主机控制器USB 主机控制器设备 FDO FDO(由 PCI 总线驱动程序创建 ) PCI 适配器PCI 设备 FDO PDO(由根总线驱动程序创建 ) 支持即插即用主要是指实现一个AddDevice 例程和一个 IRP_MJ_PNP 处理程序。这个 PnP IRP有 8

46、个次功能代码,大多数的 WDM 驱动程序需要支持这些次功能代码:IRP_MN_START_DEVICE( 启动设备 ) IRP_MN_QUERY_REMOVE_DEVIE( 查询删除 ) IRP_MN_REMOVE_DEVICE( 删除设备 ) IRP_MN_CANCEL_REMOVE_DEVICE( 取消删除 ) IRP_MN_STOP_DEVICE( 停止设备 ) IRP_MN_QUERY_STOP_DEVICE( 查询停止 ) IRP_MN_CANCEL_STOP_DEVICE( 取消停止设备 ) IRP_MN_SURPPISE_REMOVE(意外删除 ) PnP的处理:处理设备的添加和

47、删除得到分配的资源处理查询停止和查询删除消息处理停止设备消息处理意外删除消息。但是,上面只是一些基本的处理功能,驱动程序显然还要做以下的工作:仅在设备启动时允许I/O 请求在有任何打开的句柄时不允许删除设备在设备每次启动时,排队I/O 请求在处理删除请求前,等待任何I/O 请求完成在低层设备启动后处理启动0 设备消息沿设备栈向下传递不支持的IRP AddDevice 例程的工作是创建和初始化一个设备对象供当前驱动程序使用,并把该对象连接到设备栈 。 如果一个驱动程序的AddDevice 例程失败,将给它下面的任何驱动程序 (其 AddDeivice 已成功 )发送一个删除设备消息。 在 Add

48、Device 例程完成后,准备好接收删除设备消息。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 14 页 - - - - - - - - - 当添加一个 Wdm2 设备时, Unknown 总线驱动程序为它创建一个PDO。PnP管理 器把 这个PDO 传 递给Wdm2。 下面 给 出 的 Wdm2AddDevice 例程 调 用IoCreateDevice创 建Wdm2功能设 备对 象,并最 后 调用IoAttachDeviceToDeviceStack, 把该设备对

49、象挂接到设备栈。 在这个过程中, FDO和它的设备扩展被初始化,并为它建立一个设备接口。删除设备消息处理程序的最终工作是停止设备,并删除FDO。在 Wdm2 中,最终调用 IoDetachDevice从设备栈卸下该设备, 并调用 IoDeleteDevice删除设备对象, 即它的设备扩展内存。 注意删除设备请求是驱动程序卸载前的最后一个IRP。考虑各种 PnP停止消息。 当某个新硬件添加到系统或者新设备插入时,发生 PnP停止消息。 PnP管理器可能决定, 它只有通过重新分配现有的设备目前在使用的资源,才能接纳新的设备。它首先发出一个“ 查询停止 ” 消息。如果设备栈中的所有设备都同意停止,

50、则 PnP管理器发出一个 “ 停止设备 ” 请求。如果设备栈中的任何驱动程序不希望设备停止,PnP管理器发出 “ 取消停止 ” 消息,并可能通知用户目前没有足够的资源可用, 所以需要重新启动。 当资源被重新分配时, 它发送 “ 启动设备 ” 消息,带有新的资源分配。在这整个过程中,已存在的设备上的I/O 请求似乎肯定正常执行。实际上,这意味着不开始任何新的请求, 并在一个队列中保存这些请求,当设备再次启动时处理。所以用户可能注意到资源重新分配时有短暂的停顿,但I/O 请求不会失败。当用户想删除一个设备时, PnP管理器总是使用 “ 查询删除 ” 请求询问删除这个设备是否合适。所以,对于主 “

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术总结

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁