500 likes | 925 Views
PNP&Power Management&WMI. sigang@mti.xidian.edu.cn. Plug and play. 与 Hot plug 不一样 没有什么跳线,开关之类,不会引起资源冲突,因为资源不再是驱动程序自己配置,而是即插即用 (Plug and Play -- PnP) 管理器自动配置。 PNP 管理器使用主功能码为 IRP_MJ_PNP 的 IRP 与设备驱动程序交换信息和请求 这种类型的请求是新引入 WDM 中的,在以前的驱动程序中,大部分检测和配置设备的工作由设备驱动程序自己做。而 WDM 驱动程序可以让 PnP 管理器做这个工作。
E N D
PNP&Power Management&WMI sigang@mti.xidian.edu.cn
Plug and play • 与Hot plug 不一样 • 没有什么跳线,开关之类,不会引起资源冲突,因为资源不再是驱动程序自己配置,而是即插即用(Plug and Play -- PnP)管理器自动配置。 • PNP管理器使用主功能码为IRP_MJ_PNP的IRP与设备驱动程序交换信息和请求 • 这种类型的请求是新引入WDM中的,在以前的驱动程序中,大部分检测和配置设备的工作由设备驱动程序自己做。而WDM驱动程序可以让PnP管理器做这个工作。 • 为了与PnP管理器协同工作,驱动程序需要处理一些相关的IRP。 PNP&PM&WMI.doc
PnP请求在WDM中的作用 • PnP请求指示驱动程序何时以及如何配置或取消其硬件或自身的设置 。有三个对过滤器驱动程序或功能驱动程序特别重要。PnP管理器使用IRP_MN_START_DEVICE来通知功能驱动程序其硬件被赋予了什么I/O资源,以及指导功能驱动程序做任何必要的硬件或软件设置以便设备能正常工作。IRP_MN_STOP_DEVICE告诉功能驱动程序关闭设备。IRP_MN_REMOVE_DEVICE告诉功能驱动程序关闭设备并释放与之关联的设备对象
PnP请求在WDM中的作用 • PnP请求指导驱动程序完成一系列状态转换,如图所示。WORKING和STOPPED是设备的两个基本状态。当创建设备对象后,设备就立即进入STOPPED状态。WORKING状态指出设备是全部可操作的。此外,还有两个中间状态,PENDINGSTOP和PENDINGREMOVE,它们出现在WORKING状态前。SURPRISEREMOVED发生在物理硬件突然被移去的情况下。
处理IRP_MJ_PNP 的分发函数 • 使用函数指针表 • 使用switch case语句
启动设备IRP_MN_START_DEVICE • 当PnP管理器检测到硬件时,它首先参考注册表以了解有哪些过滤器驱动程序将管理该硬件 ,如果必要,它将装入这些驱动程序,并调用它们的AddDevice函数。最后AddDevice函数创建设备对象并连入设备堆栈。此后,PnP管理器将为所有设备驱动程序分配I/O资源。 • PnP管理器为每个设备创建一个资源需求列表并允许驱动程序过滤这个列表,或者对它进行更改。通常的驱动程序不用处理这个资源需求列表。通过需求列表,PnP管理器在分配资源时能协调当前系统中所有硬件的潜在资源冲突。
启动设备 • 一旦资源分配确定,PnP管理器通过向每个设备发送一个带IRP_MN_START_DEVICE副功能码的PnP请求来通知设备。 • 通常过滤器驱动程序对这个IRP不感兴趣,所以它们使用DefaultPnpHandler方式把请求向下传。而功能驱动程序正好相反,它需要在这个IRP上做大量工作,包括分配并配置额外的软件资源以及为设备操作做准备。这个工作需要在PASSIVE_LEVEL级上进行,并在低层驱动程序处理完该IRP后完成。 • 典型的处理IRP_MN_START_DEVICE 的例程如:PNP&PM&WMI.doc
停止设备IRP_MN_STOP_DEVICE • 设备停止请求通知程序关闭设备,然后PnP管理器重新分配I/O资源。 • 在硬件级,关闭设备将包括暂停或停止当前活动并阻止后来的中断。在软件级,关闭设备将涉及释放设备启动时配置的I/O资源。 • 典型的处理IRP_MN_STOP_DEVICE 的例程如:PNP&PM&WMI.doc
移除设备IRP_MN_REMOVE_DEVICE • 开始,PnP管理器通过调用驱动程序中的AddDevice函数来通知程序已经找到要管理的硬件实例,并给一个创建设备对象的机会。当设备将要被系统删除时,PnP管理器发送副功能码为IRP_MN_REMOVE_DEVICE的PnP请求。 • 因为系统在发送IRP_MN_REMOVE_DEVICE之前不一定发送IRP_MN_STOP_DEVICE,为了响应这个请求,应该做与IRP_MN_STOP_DEVICE相同事情,关闭设备,然后删除设备对象 。 • 典型的处理IRP_MN_REMOVE_DEVICE 的例程如:PNP&PM&WMI.doc
IRP_MN_SURPRISE_REMOVAL • 有时用户可能不经过任何用户接口交互操作突然地拆卸设备。如果系统检测到这种突然的删除,它就向驱动程序发送副功能码为IRP_MN_SURPRISE_REMOVAL的PnP请求,后面还会跟着一个IRP_MN_REMOVE_DEVICE请求。 • 除非以前在处理IRP_MN_QUERY_CAPABILITIES时曾设置SurpriseRemovalOK标志,否则系统将显示一个对话框,通知用户这样做是危险的。 • 我们意外拔出usb设备时可能会得到一个对话框,比如u盘,但是如果是usb键盘,可能不会得到。
IRP_MN_SURPRISE_REMOVAL • 为了响应突然删除请求,设备驱动程序应该禁止所有已注册的接口。如果应用程序事先关注这种通知,这将给应用程序一个机会关闭设备的句柄。(很多情况下应用程序都会希望在设备被移除时得到一个事件通知,这就是需要驱动程序中调用禁止接口的函数) • 然后驱动程序应释放I/O资源并向下传递请求:
Power management • WDM驱动程序中电源管理的意义 • 减少电力消耗 • 移动设备电池问题
电源管理模型 • 在Windows 2000和Windows 98中,操作系统接管了大部分电源管理工作。这是因为只有操作系统才能真正了解电源管理的内部过程。例如,系统BIOS负责的电源管理不能区分应用程序使用的屏幕和屏幕保护程序使用的屏幕之间的区别。但操作系统可以区分开这种不同,从而确定是否可以关闭显示器。 • 作为计算机全局电源策略,操作系统支持一些用户接口,用户可以通过这些接口元素控制最终的电源管理策略。这些用户接口元素包括控制面板、开始菜单上的命令、控制设备唤醒特征的API • 通过向设备发送IRP,内核的电源管理部件实现了操作系统的电源策略。WDM驱动程序主要是作为响应这些IRP的被动角色。
WDM驱动程序的角色 • 设备的某个驱动程序充当设备电源策略的管理者。通常都是由功能驱动程序充当这个角色。电源管理器可以改变整个系统的电源状态。功能驱动程序接收电源管理器发来的IRP(系统IRP),作为设备电源策略的管理者,功能驱动程序用设备理解的术语翻译这些IRP并引发新的IRP(设备IRP)。 • 当响应设备IRP时,功能驱动程序需要关心设备专有的细节。设备硬件会有自己的上下文信息,不应该在设备处于低电源期间丢失这些信息。例如,键盘驱动程序会保存锁定键(如CAPS-LOCK、NUM-LOCK、SCROLL-LOCK)、LED等信息。功能驱动程序有责任保存并恢复这些上下文信息。
WDM驱动程序的角色 • 某些设备带有唤醒特征,当外部事件发生时,这些设备可以唤醒系统;功能驱动程序应与用户协同工作以确保唤醒特征在需要时有效。 • 许多功能驱动程序还管理含有大量IRP的队列(设备读写IRP),因此当设备电源状态转变时需要停止或释放这些队列。 • 处于设备堆栈底端的总线驱动程序有责任控制设备的电流和执行任何与设备唤醒特征相关的电气步骤。 • 过滤器驱动程序通常作为电源管理IRP通过的管道,它们用专用的协议向下层驱动程序传递电源管理请求。
设备电源状态与系统电源状态 • WDM模型使用与ACPI(Advanced Configuration and Power Interface)规范相同的术语来描述电源状态 • 设备能呈现下图所描述的四种电源状态。
设备电源状态 • 在D0状态中,设备处于全供电状态。在D3状态中,设备处于无供电(或最小限度的电流)状态。中间的D1和D2状态指出设备的两个不同睡眠状态。随着设备从D0状态变化到D3状态,设备将消耗越来越少的电力,同时需要保留的当前状态上下文信息也越来越少。而设备再转变回D0状态的延迟期则相应增加。 • Microsoft规定了不同类型设备的类专用电源需求。例如,这个规范要求每个设备至少要支持D0和D3两个状态。输入设备(键盘、鼠标等)还应该支持D1状态。Modem设备需要另外支持D2状态。设备类上的这些不同规定可能来源于设备的用途和工业上的实践。 • 操作系统不直接处理设备的电源状态,由设备驱动程序专门处理
系统电源状态 • 系统使用一组与ACPI设备状态类似的系统电源状态来控制电源,如下图。
系统电源状态 • Working状态是全供电状态,计算机可以实现全部功能。程序仅能在Working状态下执行。 • 其它系统电源状态对应更小的电力需求配置,在这些系统电源状态中,计算机不能执行任何指令。Shutdown状态就是电源关闭状态。Hibernate状态是另一种Shutdown状态,它把计算机的整个状态都记录到硬盘上,因此在电源恢复供电时可以使计算机快速恢复到记录前的状态。在Hibernate和Working状态之间是三个有不同电力消耗级别的中间状态。
电源状态转换 • 系统初始化后即进入Working状态。大部分设备也以D0状态启动,但某些设备的驱动程序会在设备启动时使设备进入低电源消耗状态。在系统启动并正常运行后,这些设备的驱动程序才使设备进入一个稳定的状态,在这个状态中,系统电源处于Working状态,而设备处于的状态取决于具体活动和设备自身的能力。
电源状态转换 • 用户的活动或外部事件会导致电源状态的改变。 • 一个常见的电源状态转换情景是用户在开始菜单上选择“关闭系统”中的“等待”选项,使计算机进入等待状态。 • 在响应这个命令过程中,电源管理器首先向每个驱动程序发送带有IRP_MN_QUERY_POWER副功能码的IRP_MJ_POWER请求以询问设备能否接受即将到来的电源关闭请求。如果所有驱动程序都同意,电源管理器将发送第二个带有IRP_MN_SET_POWER副功能码的电源管理IRP,然后驱动程序把其设备置入低电源状态以响应这个IRP。如果有任何一个驱动程序否决了这个查询,电源管理器仍旧发出这个IRP_MN_SET_POWER请求,但它使用现在的电源级别。
电源状态转换 • 系统并不总是发送IRP_MN_QUERY_POWER请求。某些事件(如电池电力将要耗尽)必须被无条件接受,并且操作系统也不再发出查询请求。 • 如果查询发出后,并且驱动程序也接受了请求的电源状态,那么驱动程序将不再启动任何会妨碍未来电源状态设置请求的操作。例如,磁带机驱动程序在使一个进入低电源状态的查询请求成功返回前先确保当前没有执行备份操作。另外,该驱动程序还拒绝任何后来的备份命令,除非是另一个电源状态设置请求。
处理IRP_MJ_POWER请求 • 电源管理器与驱动程序沟通使用IRP_MJ_POWER类型的IRP • 下表列出了当前可以使用的四个副功能码。
处理IRP_MJ_POWER请求 • 所有驱动程序,包括过滤器驱动程序和功能驱动程序通常都向其下面的驱动程序传递电源管理请求。唯一的例外是IRP_MN_QUERY_POWER请求。 • IO_STACK_LOCATION的Parameters联合中的Power子结构有四个参数描述了电源管理请求,但大多数WDM驱动程序仅对其中两个参数感兴趣
处理IRP_MJ_POWER请求 • 控制如何把电源管理请求传递到低级驱动程序有特殊的规则。第一,在释放一个电源管理请求的控制之前,必须调用PoStartNextPowerIrp,即使以错误状态完成该IRP,也要这样做。做这个调用的原因是,电源管理器自己需要维持一个电源管理请求队列,所以必须通知它确实可以出队一个请求,以及向设备发送下一个请求。除了调用PoStartNextPowerIrp,还必须调用专用例程PoCallDriver(代替IoCallDriver)来向下层驱动程序发送请求。 • 下图显示了三种可能的电源请求处理过程。
处理IRP_MJ_POWER请求 • 下面函数显示了一个电源管理请求沿设备堆栈被向下传递的过程 • NTSTATUS DefaultPowerHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; return PoCallDriver(pdx->LowerDeviceObject, Irp); }
处理IRP_MJ_POWER请求 • 功能驱动程序使用两个步骤来传递IRP并执行其设备相关的动作,当进入更低的电源状态时,它先执行设备相关的步骤,然后向下传递请求。当回到更高的电源状态时,它先向下传递请求,然后在完成例程中执行设备相关的步骤。这个巧妙的嵌套操作保证了当驱动程序操作硬件时,硬件一直处于供电状态。
处理IRP_MJ_POWER请求 • 电源管理IRP到来时,程序处于一个系统线程的上下文中,不要阻塞这个线程。 • 如果设备有INRUSH特征,或者清除了设备对象中的DO_POWER_PAGABLE标志,那么电源管理器将在DISPATCH_LEVEL级上发送IRP。而当执行在DISPATCH_LEVEL级上时,不可能阻塞一个线程。 • 如果设置了DO_POWER_PAGABLE标志,会在PASSIVE_LEVEL级上收到电源管理IRP,此时,如果在服务一个系统IRP时请求了设备电源管理IRP然后阻塞,将导致死锁:电源管理器不会向程序发送设备IRP,除非系统IRP派遣例程返回,因此将永远等待下去
处理IRP_MJ_POWER请求 • 功能驱动程序在处理某些电源管理请求时会执行一些耗费时间的步骤。DDK指出,可以在用户不易察觉的范围内延迟电源管理IRP的完成,但是能够延迟并不意味着能够阻塞。在这些操作完成时,不能阻塞意味着需要使用完成例程来使这些步骤异步。 • 对IRP_MN_QUERY_POWER查询可以回答“Yes”或“No”。即可以失败该IRP。失败该IRP就是说“No”。但对于IRP_MN_SET_POWER请求却没有这样的自由:必须执行它携带的指令。
管理电源状态转换 • 设备可以有唤醒系统的能力。设备可以决定成功还是失败一个查询,决定由哪个设备电源状态来对应新系统电源状态,这些都取决于设备当前是否使用了唤醒特征。 • 可以在没有任何活动时关闭设备的电源供应,当有IRP到来时再恢复设备的电源供应。也许设备是一个“INRUSH”设备,这种设备在上电时需要大的电流,因此电源管理器需要特殊对待这种设备。 • 传统方法解决query-power和set-power操作时,即用通常的派遣例程和完成例程,需要非常精确的编码,需要面对许多复杂的因素。因此可以围绕一个有限状态机来建立电源管理程序,有限状态机可以方便地处理异步活动。 • 最开始写程序对电源管理的IRP处理可以是直接向下发送
WMI (windows management and instrumentation) • Windows 2000支持一种称为Windows管理诊断(WMI)的机制,用于管理计算机系统 • WBEM(基于Web的企业管理)是一个广泛的工业标准,而WMI是这个工业标准的Microsoft实现。 • WMI的目标是为系统管理和企业网络中管理数据的描述提供了一个模型,并尽可能独立于专用API或数据对象模型。这种独立性促进了能创建、传输,和显示控制数据的独立系统部件的发展。
WMI • 公用信息模型(CIM)是由DMTF(Distributed Management Task Force)支持的基于Web的企业管理规范,以前被称为DMTF。Microsoft命名其CIM实现为“WBEM”,其本质上是“CIM for Windows”。CIM for Windows的内核模式部分称为“WMI”。为了使CIM被更广泛地采纳,DMTF启动了一个市场行动并使用WBEM作为CIM的名称。之后Microsoft重命名其WBEM实现为WMI,并重命名WMI(内核模式部分)为“WMI extensions for WDM”。这就是说,WMI兼容CIM和WBEM规范。
WMI • WDM驱动程序以三种方式适应WMI,第一,WMI通常能响应提取性能数据的请求。第二,各种控制器应用程序可以使用WMI方式控制设备的通用特征。第三,WMI提供了一个事件通知机制,允许驱动程序通知应用程序有重要的事件发生。 • 看下图
WMI • 在WMI模型中,数据和事件被分成了消费者和生产者两类。数据块就是抽象类的实例,其概念与C++中的类概念一致。 • 如同C++中的类,WMI类也有数据成员和实现对象行为的方法。 • 数据块中的内容并不是由WMI指定,而是由数据生产者和数据的使用目的决定的。送往驱动程序的数据最有可能来自管理者本身的操作。而驱动程序发出的数据通常是某种性能的统计数据,这些数据的消费者可能是某个性能监视程序。
WMI • WMI允许存在多重命名空间,每个命名空间中包含的类属于一个或多个用户模式生产者。生产者使用平台SDK中公开的COM接口来注册Windows管理服务(Windows Management Service)。一旦Windows 2000发行,操作系统(包括所有设备驱动程序)将支持一个名为root\cimv2的命名空间,里面包含了CIM版本2。在CIMV2命名空间的结构还未确定时,Microsoft决定临时为设备驱动程序类使用另一个命名空间root\wmi。 • 可以下载WMI tools来查看wmi数据和事件或者帮助调试wmi程序,这些工具包括:WMI object browser, WMI CIM studio, WMI Event Registration tool, WMI event viwer.
WMI • WDM驱动程序可以作为WMI类实例的生产者。一个描述了驱动程序支持的各种类(驱动程序可以为这些类提供数据)的脚本称为驱动程序规划(schema)。可以使用MOF(Managed Object Format)语言定义规划。系统则维护一个称为repository的数据字典,它包含了所有已知的规划定义。如果驱动程序做得正确,系统将在初始化驱动程序时自动把规划放到repository中。
规划 • 一个最简单的WMI规划的例子PNP&PM&WMI.doc • 用MOF编译器编译这个规划并产生一个二进制文件,这个文件最后将成为驱动程序可执行文件的一个资源。在驱动程序初始化过程中,有一部分代码就是告诉WMI生产者这个资源在哪里,以便它能读取这个规划并添入到repository。 • 编译完规划后,还应该运行WMIMOFCK.EXE工具,在DDK中可以找到该工具,该工具执行检测以便规划能与WMI兼容。
WDM驱动程序与WMI • 内核模式驱动程序对WMI的支持主要是基于对主代码为IRP_MJ_SYSTEM_CONTROL的IRP的支持。为了能接收到这种IRP,必须先注册这种需求: • IoWMIRegistrationControl(fdo,WMI_ACTION_REGISTER); • 注册调用的恰当时间是在AddDevice例程中,注册完成后,一旦系统认为可以安全地向驱动程序发送系统控制IRP时,它就向驱动程序发出一个IRP_MJ_SYSTEM_CONTROL请求,以获得设备的详细注册信息。与注册调用作用相反的调用应该在RemoveDevice函数中做出: • IoWMIRegistrationControl(fdo,WMI_ACTION_DEREGISTER);
用户模式程序与WMI • WMI使用COM方式支持用户模式应用程序。通过实现几个COM接口,Windows管理服务就象消费者与生产者之间的信息流交易场所。生产者经由某个接口向Windows管理程序注册它们的存在。消费者通过接口间接地与生产者通信。 • 如果想在用户模式中访问WMI信息,首先需要与一个特殊的命名空间建立连接。在该命名空间的上下文中,可以找到WMI类的实例。可以查询并设置与该类实例相关的的数据块,调用它们的方法例程,监视它们生成的事件。