第十一篇:万丈高楼平地起-驱动编程基础知识点(三)

时间:2023-02-08 12:41:54

1.

//

    // Initialize DevicePowerState to PowerDeviceD3. PowerDeviceD3 is the lowest
    // power state for hardware. ToasterAddDevice initializes DevicePowerState to
    // the lowest power state instead of the working power state because the
    // hardware instance cannot be working until ToasterDispatchPnP processes
    // IRP_MN_START_DEVICE.
    //
    fdoData->DevicePowerState = PowerDeviceD3;


    //
    // Initialize SystemPowerState to PowerSystemWorking. PowerSystemWorking is the
    // highest power state for the system. ToasterAddDevice initializes
    // SystemPowerState to the highest power state because the system only executes
    // code, such as drivers, when the system is working.
    //
    fdoData->SystemPowerState = PowerSystemWorking;


    //
    // Notify the power manager of the initial power state of the hardware instance.
    //
    powerState.DeviceState = PowerDeviceD3;

    PoSetPowerState ( deviceObject, DevicePowerState, powerState );

对设备与系统电源状态的初始化


2.

The system dispatches IRP_MJ_CLEANUP IRPs to ToasterCleanup. ToasterCleanup
    cancels all IRPs from the driver-managed IRP queue whose file object matches
    the file object of the incoming IRP.


    IRP_MJ_CLEANUP and IRP_MJ_CLOSE are related but not identical, and are often
    confused. The system sends IRP_MJ_CLOSE to the function driver to close a
    handle returned earlier by the function driver's IRP_MJ_CREATE dispatch
    routine. ToasterCreate is the function drivers IRP_MJ_CREATE dispatch routine.
    However, ToasterClose only closes the file object handle. It does not cancel
    any IRPs in the driver-managed IRP queue that are associated with the handle.
    Thus, the system sends IRP_MJ_CLEANUP to the function driver, so that the
    driver can remove any IRPs in the driver-managed IRP queue that belonged to
    the handle that is now closed.


    ToasterCleanup processes each queued IRP in the driver-managed IRP queue and,
    if the queued IRP's file object matches that of the cleanup IRP, then the
    queued IRP is removed from the driver-managed IRP queue and added to a
    temporary IRP queue.


    After every IRP in the driver-managed IRP queue has been processed, the
    temporary IRP queue is processed. Each IRP in the temporary IRP queue is
    removed and completed with STATUS_CANCELLED.


    Note that ToasterCleanup does not call the PAGED_CODE macro because the routine
    uses a spin lock.

1) CleanUp例程的作用

2)CleanUp与Close的差别

3)CleanUp中不能使用PAGED_CODE宏的原因(spin lock)


3.

        // If the device interface is from an unrelated device we must register a
        // PnP notification for device removal to dereference and stop using the interface.

不明其意


4. 

            // Clear the IRP's cancel routine to NULL. Then determine if the system
            // has already called the IRP's cancel routine. If IoSetCancelRoutine
            // returns NULL, then the system has already called ToasterCancelQueued.
            // If IoSetCancelRoutine does not return NULL, then the system will not
            // call ToasterCancelQueued, because ToasterCancelQueued clears the IRP's
            // cancel routine to NULL.

Cancel Routine的使用方法

Cancel Routine一直是Windows驱动编程中的难点.


5.

//
                // The system has already called ToasterCancelQueued. However,
                // ToasterCancelQueued must be waiting to acquire QueueLock because
                // QueueLock was acquired before the for-loop began to process the
                // driver-managed IRP queue.
                //
                // The thread that executes ToasterCancelQueued will resume when
                // QueueLock is released outside of the for loop. ToasterCancelQueued
                // will then proceed to remove the IRP from the driver-managed IRP
                // queue, thus ToasterCleanup must not add the IRP to the temporary
                // IRP queue. Otherwise, when the temporary queue is processed at the
                // end of ToasterCleanup the same IRP would be completed twice,
                // causing a system crash because an IRP must only be completed once.
                //
                // Initialize NewRequestsQueue's list head to prevent
                // ToasterCancelQueued from causing a system crash when it attempts
                // to remove the IRP which has already been removed from the
                // driver-managed IRP queue earlier.
                //
                InitializeListHead(thisEntry);

CancelRoutine与CleanUp间对于driver-managed IRP queue的同步,由Spin lock来负责

如果CancelRoutine已经被系统调用, 则最后的IRP完成处理由CanceRoutine完成(STATUS_CANCELLED), 目前spin lock由CleanUp占有, 一旦CleanUp释放, CancelRoutine将得到调用



                // The system has not already called ToasterCancelQueued, nor
                // will it call ToasterCancelQueued because the IRP's cancel
                // routine has been cleared to NULL.
                //
                // Add the de-queued IRP to the temporary IRP queue to be completed
                // at the end of ToasterCleanup.

如果CancelRoutine未被系统调用, 则该IRP将从driver-managed IRP queue移除, 放入临时性的cleanupList, 在CleanUp最后阶段, 将该IRP完成(STATUS_CANCELLED)


6.

    The IRP might need to be canceled if the application that originated the IRP
    has been closed, but the IRP remains in the driver-managed IRP queue. The
    system then calls ToasterCancelQueued to remove the IRP from the
    driver-managed IRP queue.


    A driver that implements its own driver-managed IRP queue must supply a cancel
    routine to the system when the IRP is added to the driver-managed IRP queue
    because only the driver can correctly remove the IRP from its own
    driver-managed IRP queue.

CancelRoutine与driver-managed IRP queue的关系

CancelRoutine被系统调用的时机


这一篇主要列出一系列Windows驱动中IRP CancelRoutine的相关知识点

具体内容请参考

featured1