IRP的同步


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

简介与章节概览:


基础知识:

A、应用程序对设备的同步异步操作

B、IRP的同步异步完成

C、取消例程

D、StartIO例程与自定义的StartIo例程

E、中断服务例程和DPC例程


数据结构与API:

OVERLAPPED

IoCompleteRequest(...), return status_success;

IoMarkIrpPending(pIrp), return status_pending;


IoSetCancelRoutine(pIrp,CancelReadIRP);

//显式的调用CancelIo,其实在关闭设备时会自动运行CancelIo

CancelIo(hDevice);


KDEVICE_QUEUE(pirp,lock, busy)

IoStartNextPacket

DISPATCH_LEVEL

//将IRP插入系统的队列

IoStartPacket(pDevObj,pIrp,0,OnCancelIRP);


KDEVICE_QUEUE(pirp,lock, busy)

KeInitializeDeviceQueue

KeInsertDeviceQueue

KeRemoveDeviceQueue



应用程序对设备的同步异步操作       

同步操作与异步操作原理 

ReadFile(...),WriteFile(...),DeviceIoControl(...)



WaitForSingleObject(...)





同步操作设备

HANDLE
WINAPI
CreateFileW(
    _In_ LPCWSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
);
BOOL
WINAPI
ReadFile(
    _In_ HANDLE hFile,
    _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToRead,
    _Out_opt_ LPDWORD lpNumberOfBytesRead,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
);



异步操作设备(方式一)


typedef struct _OVERLAPPED {

    ULONG_PTR Internal;

    ULONG_PTR InternalHigh;

    union {

        struct {

            DWORD Offset;

            DWORD OffsetHigh;

        } DUMMYSTRUCTNAME;

        PVOID Pointer;

    } DUMMYUNIONNAME;


    HANDLE  hEvent;

} OVERLAPPED, *LPOVERLAPPED;



异步操作设备(方式二)


BOOL

WINAPI

ReadFileEx(

    _In_ HANDLE hFile,

    _Out_writes_bytes_opt_(nNumberOfBytesToRead) __out_data_source(FILE) LPVOID lpBuffer,

    _In_ DWORD nNumberOfBytesToRead,

    _Inout_ LPOVERLAPPED lpOverlapped,

    _In_ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine

    );


APC:异步过程调用

APC队列:回调函数的队列

警惕模式:Alertable


IRP的同步完成与异步完成       

IRP的同步完成

Win32API: CreateFile(...)

Ntdll.dll: NtCreateFile(...)

ntoskrnl.exe本地服务(IO管理器):NtCreateFile(...)

A---b---c: app--->kernel

C--b--a: kernel-->app




IRP的异步完成

第一种:

overlapped.hEvent = createEvent(...);//事件是我们自己创建的

ReadFile(handle, buf, size, &dwRetSize, &overlapped);


第二种:

ReadFileEx(....., &overlapped, ioCompletionRoutine);


GetLastErrorCode(...): Pending


IoMarkIRPPending(...)




取消IRP

IoSetCancelRoutine(pIrp,CancelReadIRP);


//显式的调用CancelIo,其实在关闭设备时会自动运行CancelIo

CancelIo(hDevice);


PDRIVER_CANCEL
IoSetCancelRoutine(
    _Inout_  PIRP Irp,
    _In_opt_ PDRIVER_CANCEL CancelRoutine
    )
VOID
CancelReadIRP(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
KdPrint(("Enter CancelReadIRP\n"));
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
DeviceObject->DeviceExtension;
//设置完成状态为STATUS_CANCELLED
 Irp->IoStatus.Status = STATUS_CANCELLED;
 Irp->IoStatus.Information = 0;// bytes xfered
 IoCompleteRequest( Irp, IO_NO_INCREMENT );
//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);
KdPrint(("Leave CancelReadIRP\n"));
}



StartIO例程       

并行执行与串行执行



StartIO例程

KDEVICE_QUEUE(pirp,lock, busy)

IoStartNextPacket


DISPATCH_LEVEL

//将IRP插入系统的队列

IoStartPacket(pDevObj,pIrp,0,OnCancelIRP);


示例 



自定义的StartIO

多个串行化队列 

KDEVICE_QUEUE(pirp,lock, busy)

KeInitializeDeviceQueue

KeInsertDeviceQueue

KeRemoveDeviceQueue


示例



中断服务例程       

中断操作的必要性


中断优先级


中断服务例程(isr)



DPC例程       

延迟过程调用例程(dpc)



dpcforisr 




好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***