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
***【在线视频教程】***