用户拔出设备

当系统运行时,用户可以通过以下两种方式之一删除设备:有 条不紊地删除设备,这意味着用户通知系统设备即将 (删除,例如,使用拔出或弹出硬件程序) ;或 意外删除,这意味着用户在不通知系统的情况下拔下设备。 如果总线支持意外删除 (例如 USB) ,则设备的驱动程序必须能够处理设备的突然消失。

有序删除

用户通过使用系统的拔出或弹出硬件程序、通过使用设备管理器禁用设备或推送可弹出设备的弹出按钮来请求删除。 框架允许删除或禁用设备,除非驱动程序具有:

对于支持该设备的每个函数和筛选器驱动程序,框架从驱动程序堆栈中最高的驱动程序开始,按顺序一次执行一个驱动程序的以下操作:

  1. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoSuspend 回调函数。

  2. 框架会停止驱动程序的所有电源托管 I/O 队列。

  3. 如果硬件和驱动程序支持 DMA,框架将驱动程序的 EvtDmaEnablerSelfManagedIoStopEvtDmaEnablerFlushEvtDmaEnablerDisable 回调 函数 (,如果它们存在) 创建的每个 DMA 通道。

  4. 框架 (调用驱动程序的 EvtDeviceD0ExitPreInterruptsDisabled 回调函数(如果存在) ),然后调用驱动程序的 EvtInterruptDisable 回调函数 (如果存在每个中断) ,则驱动程序可以禁用设备中断。

  5. 框架 (调用驱动程序的 EvtDeviceD0Exit 回调函数(如果存在) )。

  6. 框架调用驱动程序的 EvtDeviceReleaseHardware 回调函数 (如果它存在) ,则向其传递 PnP 管理器分配给设备的硬件资源列表。

  7. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoFlush 回调函数。

  8. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoCleanup 回调函数。

总线驱动程序是堆栈中最后调用的驱动程序。 当框架调用总线驱动程序的 EvtDeviceD0Exit 回调函数时,回调函数将设备的电源状态 (总线) 的子设备设置为 D3。 总线驱动程序可以通过调用 WdfDeviceInitSetReleaseHardwareOrderOnFailure 来控制框架何时调用其 EvtDeviceReleaseHardware 回调函数。

意外删除

用户意外拔下设备。 设备总线的总线驱动程序发现设备缺失,并调用 WdfChildListUpdateChildDescriptionAsMissing

对于支持该设备的每个函数和筛选器驱动程序,框架从驱动程序堆栈中最高的驱动程序开始,按顺序一次执行一个驱动程序的以下操作:

  1. 框架调用驱动程序的 EvtDeviceSurpriseRemoval 回调函数 ((如果存在) )。
  2. 如果设备处于工作状态 (D0) 拔出设备时的状态:
    1. 框架会停止驱动程序的所有电源托管 I/O 队列。
    2. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoSuspend 回调函数。
    3. 如果硬件和驱动程序支持 DMA,框架将驱动程序的 EvtDmaEnablerSelfManagedIoStopEvtDmaEnablerFlushEvtDmaEnablerDisable 回调 函数 (,如果它们存在) 创建的每个 DMA 通道。
    4. 框架调用驱动程序的 EvtDeviceD0ExitPreInterruptsDisabledEvtInterruptDisable 回调函数 ((如果它们存在) ),以便驱动程序可以禁用设备中断。
    5. 框架 (调用驱动程序的 EvtDeviceD0Exit 回调函数(如果存在) )。
  3. 框架调用驱动程序的 EvtDeviceReleaseHardware 回调函数 (如果它存在) ,将 PnP 管理器分配给设备的硬件资源列表传递。
  4. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoFlush 回调函数。
  5. 如果驱动程序使用自托管 I/O,框架将调用驱动程序的 EvtDeviceSelfManagedIoCleanup 回调函数。

请注意,设备随时可能会意外删除。 因此,框架可能会在前面步骤中显示的时间调用驱动程序的 EvtDeviceSurpriseRemoval 回调函数。 例如,如果用户在设备进入低功耗状态时意外拔下电源,框架可能会在调用 EvtDeviceReleaseHardware 回调函数后调用 EvtDeviceSurpriseRemoval 回调函数。 不得以假定在特定序列中调用 EvtDeviceSurpriseRemoval 回调函数和其他回调函数的方式编写代码。

此外,框架不会将设备的 EvtDeviceSurpriseRemoval 回调函数与该设备前面步骤中列出的任何回调函数同步。 因此, EvtDeviceSurpriseRemoval 回调函数可能会运行,而前面列出的另一个回调函数也在运行。