程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 關於DPC和workitem的簡單用法,dpcworkitem

關於DPC和workitem的簡單用法,dpcworkitem

編輯:關於C語言

關於DPC和workitem的簡單用法,dpcworkitem


這個隨筆是記錄我半個月左右的時間,從想法到查資料請教,以及到實踐的成果。

我想實現的是,隔定時時間寫文件,本以為調用寫的函數就可以實現了,結果各種BSOD,IRQL_NOT_LESS_OR_EQUAL,這個藍屏提示,結果是函數的IRQL導致的,內核函數都有IRQL,我是想在DISPATCH_LEVEL中運行低級別的PASSIVE_LEVEL,因為寫函數就是在PASSIVE_LEVEL上運行的。解決方法是,使用DPC,IoQueueWorkItem。下面的代碼是我簡單的測試了我的想法,給文件中只寫入了時間和簡單的數據結構信息,只適合新手,全部代碼如下(注意紅色標記代碼):

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include "ntddk.h"
  4 
  5 #define WRITE_FILE_INTERVAL    -10000 * 1000 * 10
  6 typedef struct my_info{
  7         int age;
  8         int weight;
  9         char* name;
 10 }myInfo, *PmyInfo;
 11 VOID ThreadStart(IN PVOID StartContext);
 12 
 13 VOID CustomDpc(IN struct _KDPC *Dpc, 
 14                              IN PVOID DeferredContext,
 15                              IN PVOID SystemArgument1, 
 16                              IN PVOID SystemArgument2);
 17                              
 18 VOID SyncTechUnload(IN PDRIVER_OBJECT DriverObject);
 19 //VOID workItem();
 20 NTSTATUS GetLocalTime( OUT PTIME_FIELDS  timeFields );
 21 VOID TestFile(IN PDEVICE_OBJECT  DeviceObject,
 22     IN PVOID  Context);
 23 
 24 KTIMER Timer;   //?????????????????
 25 PDEVICE_OBJECT DeviceObject;
 26 PIO_WORKITEM pIoWorkItem;
 27 LARGE_INTEGER DueTime; 
 28 KDPC Dpc; 
 29 HANDLE hThread;
 30 
 31 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
 32 {
 33         
 34         OBJECT_ATTRIBUTES ObjectAttributes;
 35         CLIENT_ID  CID;
 36         NTSTATUS status;
 37         UNICODE_STRING DeviceName, Win32Device;
 38         
 39         
 40         KdPrint(("dpc:DriverEntry Cur Process:%s Cur IRQL:%d\n", 
 41         (char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql()));
 42     
 43         RtlInitUnicodeString(&DeviceName, L"\\Device\\jay0");
 44         RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\jay0");
 45         status = IoCreateDevice(DriverObject,
 46                                                         10,
 47                                                         &DeviceName,
 48                                                         FILE_DEVICE_UNKNOWN,
 49                                                         0,
 50                                                         FALSE,
 51                                                         &DeviceObject);
 52         if(!NT_SUCCESS(status))
 53             return status;
 54         if(!DeviceObject)
 55             {
 56                 KdPrint(("dpc:DeviceObject is failure\n"));    
 57                 return STATUS_UNEXPECTED_IO_ERROR;
 58             }
 59         //初始化定時器
 60         KeInitializeTimer(&Timer);
 61         DriverObject->DriverUnload = SyncTechUnload;
 62         InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
 63         //創建一個系統線程
 64         status = PsCreateSystemThread(
 65                     &hThread,
 66                     GENERIC_READ|GENERIC_WRITE,
 67                     &ObjectAttributes,
 68                     NtCurrentProcess(),
 69                     &CID,
 70                     (PKSTART_ROUTINE)ThreadStart,
 71                     NULL
 72         );
 73         if (!NT_SUCCESS(status))
 74             {
 75                 KdPrint(("dpc:PsCreateSystemThread failure!\n"));
 76                 return 0;
 77             }
 78         ZwClose(hThread);
 79         KdPrint(("dpc:Exit\n"));
 80         return STATUS_SUCCESS;
 81 }
 82 
 83 VOID ThreadStart(IN PVOID StartContext)
 84 {
 85       
 86     PmyInfo pmyInfo;
 87     KdPrint(("dpc:Cur Process: %s IRQL:%d\n",
 88             (char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql()));
 89     pmyInfo = ExAllocatePool(NonPagedPool, sizeof(myInfo));
 90     pmyInfo->age = 23;
 91     pmyInfo->weight = 60;
 92     pmyInfo->name = "zc";
 93     //KdPrint(("dpc: my age is %d , my weight is %d \n", context->age, context->weight));
 94     DueTime = RtlConvertLongToLargeInteger(WRITE_FILE_INTERVAL);
 95     //初始化一個Dpc
 96     //這個CustomDpc是自定義的函數,運行在DISPATCH_LEVEL上,後面的參數myInfo是該函數的參數
 97     KeInitializeDpc(&Dpc, (PKDEFERRED_ROUTINE)CustomDpc, pmyInfo);
 98     //設置DPC定時器
 99     KeSetTimer(&Timer, DueTime, &Dpc);
100     //等待定時器
101     KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);
102     KdPrint(("dpc:ThreadStart time expire"));
103     return;
104 }
105 
106 //簡單輸出進程名和當前的IRQL,注意該函數運行在dispatch級別
107 
108 VOID CustomDpc(IN struct _KDPC *Dpc, 
109                              IN PmyInfo pmyInfo,
110                              IN PVOID SystemArgument1, 
111                              IN PVOID SystemArgument2)
112 {
113         
114     
115         KdPrint(("dpc:CustomDpc Process: %s IRQL:%d\n",
116                 (char*)((ULONG)PsGetCurrentProcess()+0x174), KeGetCurrentIrql()));
117      // KdPrint(("dpc: my age is %d , my weight is %d, my name is %s\n",
118       //        pmyInfo->age, pmyInfo->weight, pmyInfo->name));
119             
120       //使用IoAllocateWorkItem分配一個ioworkitem  
121       pIoWorkItem = IoAllocateWorkItem(DeviceObject);
122      // IoInitializeWorkItem(DeviceObject,pIoWorkItem); 
123       
124      
125       if(pIoWorkItem)
126       {
127           //插入一個workitem, 其中TestFile就是我要寫文件的函數,第四個參數也是該函數的參數
128           IoQueueWorkItem(pIoWorkItem, (PIO_WORKITEM_ROUTINE)TestFile, DelayedWorkQueue, pmyInfo);
129       }
130       //由於要定時寫,因此再次設置定時器,如果不設置只寫一次
131         KeSetTimer(&Timer, DueTime, Dpc);
132 }
133 
134 
135 NTSTATUS
136 GetLocalTime( OUT PTIME_FIELDS  timeFields )
137 /*++
138 --*/
139 {
140     NTSTATUS        status = STATUS_SUCCESS;
141     LARGE_INTEGER   sysTime,locTime;
142 
143     KeQuerySystemTime( &sysTime );
144     ExSystemTimeToLocalTime( &sysTime,&locTime );
145     RtlTimeToTimeFields( &locTime,timeFields );
146     
147     return STATUS_SUCCESS;
148 
149 }
150 
151 VOID TestFile(IN PDEVICE_OBJECT  DeviceObject,
152     IN PmyInfo pmyInfo)
153 
154 {
155          TIME_FIELDS time;
156      UNICODE_STRING string;
157      HANDLE hFile;
158      IO_STATUS_BLOCK iostatus;
159      NTSTATUS status;
160      WCHAR pBuffer[200];
161      OBJECT_ATTRIBUTES objattr;
162      LARGE_INTEGER  ByteOffset;  
163      KIRQL irql;
164         
165      RtlInitUnicodeString(&string, L"\\??\\C:\\Log\\1.log");
166      InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);
167      GetLocalTime(&time);
168          irql = KeGetCurrentIrql();
169          KdPrint(("dpc: cur irql=%d", irql));
170      //打開文件
171      status = ZwCreateFile(&hFile, FILE_APPEND_DATA,
172                                                     &objattr, &iostatus,
173                                                       NULL, FILE_ATTRIBUTE_NORMAL,
174                                                         FILE_SHARE_WRITE,
175                                                     FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
176         
177            swprintf( pBuffer,L"[%d-%d-%d-%d-%d-%d]",
178             time.Year,
179             time.Month,
180             time.Day,
181             time.Hour,
182             time.Minute,
183             time.Second);
184            KdPrint(("dpc: %S", pBuffer)); 
185               KdPrint(("dpc: my age is %d , my weight is %d, my name is %s\n",
186                                                  pmyInfo->age, pmyInfo->weight, pmyInfo->name));
187          //寫文件
188          status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
189                                                           pBuffer, wcslen(pBuffer)*sizeof(WCHAR), NULL, NULL);
190          //寫入換行符
191          status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
192                                                                 L"\n", sizeof(WCHAR), NULL, NULL);
193 
194          //關閉文件句柄
195          ZwClose(hFile);
196          //釋放內存
197         // ExFreePool(pBuffer);
198        
199        
200 }
201 
202 VOID SyncTechUnload(IN PDRIVER_OBJECT DriverObject)
203 {
204     
205     KeCancelTimer(&Timer);
206     IoFreeWorkItem(pIoWorkItem);
207     IoDeleteDevice(DriverObject->DeviceObject);
208     KdPrint(("dpc:DpcTest unload!\n"));
209 
210 }

代碼賦值粘貼,編譯後安裝.sys,可直接運行。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved