(十六)、IRP的同步与异步
一、IRP的同步完成与异步完成
1、IoMarkIrpPending
IoMarkIrpPending函数的作用就是告诉IoManager不要回收资源
2、FILE_FLAG_OVERLAPPED
CreateFile的倒数第二个成员
三环代码
// syn_asy三环代码.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <stdio.h> #include <Windows.h> using namespace std; int main() { HANDLE hDevice = CreateFile(TEXT("\\\\.\\MyDDKLink"), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hDevice == INVALID_HANDLE_VALUE) { printf("打开设备失败 %d\n",GetLastError()); return -1; } DWORD dwret; OVERLAPPED ol = { NULL }; for (int i = 0; i < 100; i++) { ReadFile(hDevice, NULL, 0, &dwret, &ol); } CloseHandle(hDevice);//在内核会触发 MJ_cleanuP 与Close派遣函数// getchar(); return 0; }
0环代码
#include <ntddk.h> LIST_ENTRY ListHead; VOID Unload(PDRIVER_OBJECT driver) { UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject); DbgPrint("Driver Unload\n"); } NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("Create 成功\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入read\n"); IoMarkIrpPending(Irp); InsertHeadList(&ListHead, &Irp->Tail.Overlay.ListEntry);//将Irp插入链表// //Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; //IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开读函数\n"); return STATUS_PENDING;; } NTSTATUS CleanUp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入CleanUp\n"); while (!IsListEmpty(&ListHead)) { PLIST_ENTRY pEntry = RemoveHeadList(&ListHead); PIRP pendingIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);//根据结构体某一成员的地址获取结构体的基地址// pendingIrp->IoStatus.Status = STATUS_SUCCESS; pendingIrp->IoStatus.Information = 0; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); DbgPrint("完成Irp操作\n"); } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开CleanUp\n"); return STATUS_SUCCESS; } NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入Close\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开Close\n"); return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDDKName"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); PDEVICE_OBJECT DeviceObject; DbgPrint("Driver Load\n"); NTSTATUS status; status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice error\n"); return status; } status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateSymbolicLink error\n"); IoDeleteDevice(DeviceObject); return status; } InitializeListHead(&ListHead); driver->MajorFunction[IRP_MJ_CREATE] = Create; driver->MajorFunction[IRP_MJ_READ] = Read; driver->MajorFunction[IRP_MJ_CLEANUP] = CleanUp; driver->MajorFunction[IRP_MJ_CLOSE] = Close; DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; driver->DriverUnload = Unload; return STATUS_SUCCESS; }
在该实验中Read派遣函数的IRP被放入到链表中,同时挂起,当派遣函数CleanUp运行的时候才被重新运行
二、取消IRP
IoSetCancelRoutine
VOID
(*PDRIVER_CANCEL)(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
代码(这是一份错误的代码,怎么运行怎么蓝屏,我不是很理解)
0环代码
#include <ntddk.h> LIST_ENTRY ListHead; VOID Unload(PDRIVER_OBJECT driver) { UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject); DbgPrint("Driver Unload\n"); } NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("Create 成功\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID CancelRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { DbgPrint("进入取消函数\n"); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开取消函数\n"); } NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入read\n"); IoSetCancelRoutine(Irp, CancelRoutine); IoMarkIrpPending(Irp); //InsertHeadList(&ListHead, &Irp->Tail.Overlay.ListEntry);//将Irp插入链表// //Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; //IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开读函数\n"); return STATUS_PENDING; } NTSTATUS CleanUp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入CleanUp\n"); while (!IsListEmpty(&ListHead)) { PLIST_ENTRY pEntry = RemoveHeadList(&ListHead); PIRP pendingIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);//根据结构体某一成员的地址获取结构体的基地址// pendingIrp->IoStatus.Status = STATUS_SUCCESS; pendingIrp->IoStatus.Information = 0; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); DbgPrint("完成Irp操作\n"); } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开CleanUp\n"); return STATUS_SUCCESS; } NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入Close\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开Close\n"); return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { NTSTATUS status; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDDKName"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); PDEVICE_OBJECT DeviceObject; DbgPrint("Driver Load\n"); status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice error\n"); return status; } status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateSymbolicLink error\n"); IoDeleteDevice(DeviceObject); return status; } InitializeListHead(&ListHead); driver->MajorFunction[IRP_MJ_CREATE] = Create; driver->MajorFunction[IRP_MJ_READ] = Read; driver->MajorFunction[IRP_MJ_CLEANUP] = CleanUp; driver->MajorFunction[IRP_MJ_CLOSE] = Close; DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; driver->DriverUnload = Unload; return STATUS_SUCCESS; }
三、StartIo
StartIo主要任务就是将并行的Irp进行串行处理
IoStartPacket
DRIVER_STARTIO DriverStartio;
void DriverStartio(
[in, out] _DEVICE_OBJECT *DeviceObject,
[in, out] _IRP *Irp
)
{...}
IoStartNextPacket
取消函数会首先获取一个自旋锁,如果当前Irp不等于提供的Irp,就需要我们释放系统发取消自旋锁,参考:
0环代码
#include <ntddk.h> LIST_ENTRY ListHead; VOID Unload(PDRIVER_OBJECT driver) { UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject); DbgPrint("Driver Unload\n"); } NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("Create 成功\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } void DriverStartio( struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp ) { LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 100 * 1000); DbgPrint("进入StartIo\n"); KeDelayExecutionThread(KernelMode, FALSE, &timeout); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); IoStartNextPacket(DeviceObject, TRUE); DbgPrint("离开StartIo\n"); } VOID CancelRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { DbgPrint("进入取消函数\n"); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开取消函数\n"); } NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入read\n"); //IoSetCancelRoutine(Irp, CancelRoutine); IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, CancelRoutine);//将并行Irp串行处理// 将100个Irp自动插入一个链表中,串形处理// //InsertHeadList(&ListHead, &Irp->Tail.Overlay.ListEntry);//将Irp插入链表// //Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; //IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开读函数\n"); return STATUS_PENDING; } NTSTATUS CleanUp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入CleanUp\n"); while (!IsListEmpty(&ListHead)) { PLIST_ENTRY pEntry = RemoveHeadList(&ListHead); PIRP pendingIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);//根据结构体某一成员的地址获取结构体的基地址// pendingIrp->IoStatus.Status = STATUS_SUCCESS; pendingIrp->IoStatus.Information = 0; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); DbgPrint("完成Irp操作\n"); } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开CleanUp\n"); return STATUS_SUCCESS; } NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入Close\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开Close\n"); return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { NTSTATUS status; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDDKName"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); PDEVICE_OBJECT DeviceObject; DbgPrint("Driver Load\n"); status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice error\n"); return status; } status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateSymbolicLink error\n"); IoDeleteDevice(DeviceObject); return status; } InitializeListHead(&ListHead); driver->DriverStartIo = DriverStartio; driver->MajorFunction[IRP_MJ_CREATE] = Create; driver->MajorFunction[IRP_MJ_READ] = Read; driver->MajorFunction[IRP_MJ_CLEANUP] = CleanUp; driver->MajorFunction[IRP_MJ_CLOSE] = Close; DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; driver->DriverUnload = Unload; return STATUS_SUCCESS; }
3环代码
// syn_asy三环代码.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <stdio.h> #include <Windows.h> using namespace std; int main() { HANDLE hDevice = CreateFile(TEXT("\\\\.\\MyDDKLink"), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hDevice == INVALID_HANDLE_VALUE) { printf("打开设备失败 %d\n", GetLastError()); return -1; } DWORD dwret; OVERLAPPED ol = { NULL }; for (int i = 0; i < 100; i++) { ReadFile(hDevice, NULL, 0, &dwret, &ol); } CloseHandle(hDevice);//在内核会触发 MJ_cleanuP 与Close派遣函数// getchar(); return 0; }
四、自定义StartIo
迷迷糊糊的,毛啊 //代码好像写的有点问题。。。
#include <ntddk.h> LIST_ENTRY ListHead; KDEVICE_QUEUE DeviceQueue; VOID Unload(PDRIVER_OBJECT driver) { UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject); DbgPrint("Driver Unload\n"); } NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("Create 成功\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } void DriverStartio( struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp ) { LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 100 * 1000); if (DeviceObject->CurrentIrp != Irp) { IoReleaseCancelSpinLock(Irp->Cancel); return; } DbgPrint("进入StartIo\n"); KeDelayExecutionThread(KernelMode, FALSE, &timeout); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); IoStartNextPacket(DeviceObject, TRUE); DbgPrint("离开StartIo\n"); } VOID CancelRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { DbgPrint("进入取消函数\n"); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开取消函数\n"); } VOID MyStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) { LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 3000 * 100); PIRP CurrentIrp = Irp; PKDEVICE_QUEUE_ENTRY QueueEntry = NULL; DbgPrint("进入MyStartIo\n"); while (TRUE) { CurrentIrp->IoStatus.Status = STATUS_SUCCESS; CurrentIrp->IoStatus.Information = 0; IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT); QueueEntry = KeRemoveDeviceQueue(&DeviceQueue); if (QueueEntry == NULL) { break; } CurrentIrp = CONTAINING_RECORD(QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry); KeDelayExecutionThread(KernelMode, FALSE, &timeout); } DbgPrint("离开MyStartIo\n"); } NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入read\n"); //IoSetCancelRoutine(Irp, CancelRoutine); IoMarkIrpPending(Irp); if (!KeInsertDeviceQueue(&DeviceQueue, &Irp->Tail.Overlay.DeviceQueueEntry)) { MyStartIo(DeviceObject,Irp); } //IoStartPacket(DeviceObject, Irp, NULL, CancelRoutine);//将并行Irp串行处理// 将100个Irp自动插入一个链表中,串形处理// //InsertHeadList(&ListHead, &Irp->Tail.Overlay.ListEntry);//将Irp插入链表// //Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; //IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开读函数\n"); return STATUS_PENDING; } NTSTATUS CleanUp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入CleanUp\n"); while (!IsListEmpty(&ListHead)) { PLIST_ENTRY pEntry = RemoveHeadList(&ListHead); PIRP pendingIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);//根据结构体某一成员的地址获取结构体的基地址// pendingIrp->IoStatus.Status = STATUS_SUCCESS; pendingIrp->IoStatus.Information = 0; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); DbgPrint("完成Irp操作\n"); } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开CleanUp\n"); return STATUS_SUCCESS; } NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("进入Close\n"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("离开Close\n"); return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { NTSTATUS status; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDDKName"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); PDEVICE_OBJECT DeviceObject; DbgPrint("Driver Load\n"); status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateDevice error\n"); return status; } status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("IoCreateSymbolicLink error\n"); IoDeleteDevice(DeviceObject); return status; } InitializeListHead(&ListHead); KeInitializeDeviceQueue(&DeviceQueue); driver->DriverStartIo = DriverStartio; driver->MajorFunction[IRP_MJ_CREATE] = Create; driver->MajorFunction[IRP_MJ_READ] = Read; driver->MajorFunction[IRP_MJ_CLEANUP] = CleanUp; driver->MajorFunction[IRP_MJ_CLOSE] = Close; DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; driver->DriverUnload = Unload; return STATUS_SUCCESS; }
// syn_asy三环代码.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <stdio.h> #include <Windows.h> using namespace std; DWORD WINAPI ThreadProc(PVOID Context) { DWORD dwRet; HANDLE hDevice = *(PHANDLE)Context; OVERLAPPED ol = { NULL }; ol.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ReadFile(hDevice, NULL, 0, &dwRet, &ol); //Sleep(3000); //SetEvent(ol.hEvent); WaitForSingleObject(hDevice, INFINITE); printf("完成!!!\n"); return 0; } int main() { HANDLE hDevice = CreateFile(TEXT("\\\\.\\MyDDKLink"), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hDevice == INVALID_HANDLE_VALUE) { printf("打开设备失败 %d\n", GetLastError()); return -1; } for (int i = 0; i < 100; i++) { CreateThread(NULL, 0, ThreadProc, &hDevice, 0, NULL); } while (true) { Sleep(2000); } CloseHandle(hDevice);//在内核会触发 MJ_cleanuP 与Close派遣函数// getchar(); return 0; }