关于内核定时器,DPC,线程的使用

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-26 10:59   19   0
  1. 关于内核定时器,及DPC的使用,看来一些代码,这个估计是比较规范的用法了,很基础,希望对新手有帮助
  2. 注意,这里的定时器不太精确!
  1. #include <ntddk.h>
  2. typedef struct _DEVICE_EXTENSION {
  3. LIST_ENTRY list_head;
  4. KSPIN_LOCK list_lock;
  5. PVOID thread_pointer;
  6. BOOLEAN terminate_thread;
  7. KEVENT request_event;
  8. KTIMER my_timer;
  9. KDPC KiTimerExpireDpc;
  10. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  11. #define dprintf if (DBG) DbgPrint
  12. #define nprintf DbgPrint
  13. #define DEVICE_NAME L"\\Device\\devhello" // Driver Name
  14. #define LINK_NAME L"\\DosDevices\\hello" // Link Name
  15. //
  16. // The device driver IOCTLs
  17. //
  18. #define IOCTL_BASE 0x800
  19. #define MY_CTL_CODE(i) \
  20. CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)
  21. #define IOCTL_HELLO MY_CTL_CODE(0)
  22. /
  23. //函数声明
  24. NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
  25. NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
  26. NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
  27. VOID DriverUnload(PDRIVER_OBJECT pDriverObj);
  28. NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
  29. VOID
  30. KiTimerExpirationFunction (
  31. IN struct _KDPC *Dpc,
  32. IN PVOID DeferredContext,
  33. IN PVOID SystemArgument1,
  34. IN PVOID SystemArgument2
  35. );
  36. NTSTATUS ThreadFunc ( IN PVOID Context);
  37. /
  38. NTSTATUS
  39. DriverEntry(
  40. PDRIVER_OBJECT pDriverObj,
  41. PUNICODE_STRING pRegistryString
  42. )
  43. {
  44. NTSTATUS status = STATUS_SUCCESS;
  45. UNICODE_STRING ustrLinkName;
  46. UNICODE_STRING ustrDevName;
  47. PDEVICE_OBJECT device_object;
  48. PDEVICE_EXTENSION device_extension;
  49. HANDLE thread_handle;
  50. /*
  51. 在驱动中是以100纳秒为单位的
  52. 1000纳秒=1微秒
  53. 1000微秒=1毫秒
  54. 1000毫秒=1秒 10*1000*1000
  55. */
  56. LARGE_INTEGER duetime = {0};
  57. #define POLLING_INTERVAL 3000
  58. dprintf("[hello] DriverEntry\n");
  59. pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
  60. pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
  61. pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
  62. pDriverObj->DriverUnload = DriverUnload;
  63. RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
  64. status = IoCreateDevice(pDriverObj,
  65. sizeof(DEVICE_EXTENSION),
  66. &ustrDevName,
  67. FILE_DEVICE_UNKNOWN,
  68. 0,
  69. FALSE,
  70. &device_object);
  71. if(!NT_SUCCESS(status)) {
  72. dprintf("[hello] IoCreateDevice = 0x%x\n", status);
  73. return status;
  74. }
  75. RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
  76. status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
  77. if(!NT_SUCCESS(status)) {
  78. dprintf("[hello] IoCreateSymbolicLink = 0x%x\n", status);
  79. IoDeleteDevice(device_object);
  80. return status;
  81. }
  82. device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
  83. InitializeListHead(&device_extension->list_head);
  84. KeInitializeSpinLock(&device_extension->list_lock);
  85. KeInitializeEvent( &device_extension->request_event,
  86. NotificationEvent,
  87. FALSE);
  88. // KeInitializeTimer(&my_timer);//这是个旧的函数
  89. KeInitializeTimerEx(&device_extension->my_timer, NotificationTimer);
  90. // 初始化定时器过期的DPC对象
  91. KeInitializeDpc(&device_extension->KiTimerExpireDpc,
  92. (PKDEFERRED_ROUTINE)KiTimerExpirationFunction, (PVOID) device_object);
  93. // KeSetTimer(&my_timer,timeout,&KiTimerExpireDpc); 仅仅只能设置一次
  94. // KeSetTimerEx(&my_timer, timeout, period, &KiTimerExpireDpc);这个可以循环设置
  95. KeSetTimerEx(&device_extension->my_timer, duetime, POLLING_INTERVAL, &device_extension->KiTimerExpireDpc);
  96. // KeSetTimerEx语句启动周期定时器。由于duetime参数是0,
  97. // 所以定时器立即进入信号态。
  98. // 然后每隔POLLING_INTERVAL=3秒触发一次。
  99. device_extension->terminate_thread = FALSE;
  100. status = PsCreateSystemThread(
  101. &thread_handle,
  102. (ACCESS_MASK) 0L,
  103. NULL,
  104. NULL,
  105. NULL,
  106. ThreadFunc,
  107. device_object
  108. );
  109. if (!NT_SUCCESS(status))
  110. {
  111. IoDeleteDevice(device_object);
  112. return status;
  113. }
  114. status = ObReferenceObjectByHandle(
  115. thread_handle,
  116. THREAD_ALL_ACCESS,
  117. NULL,
  118. KernelMode,
  119. &device_extension->thread_pointer,
  120. NULL
  121. );
  122. if (!NT_SUCCESS(status))
  123. {
  124. ZwClose(thread_handle);
  125. device_extension->terminate_thread = TRUE;//如果出错就关闭创建的线程
  126. KeSetEvent(
  127. &device_extension->request_event,
  128. (KPRIORITY) 0,
  129. FALSE
  130. );
  131. IoDeleteDevice(device_object);
  132. return status;
  133. }
  134. ZwClose(thread_handle);
  135. return STATUS_SUCCESS;
  136. }
  137. VOID
  138. KiTimerExpirationFunction (
  139. IN struct _KDPC *Dpc,
  140. IN PVOID DeferredContext,
  141. IN PVOID SystemArgument1,
  142. IN PVOID SystemArgument2
  143. )
  144. {
  145. PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext;
  146. PDEVICE_EXTENSION device_extension = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
  147. //kesetevent 必需在较低级别用
  148. //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  149. //dprintf("level in timer function is %x\n",KeGetCurrentIrql());
  150. dprintf("haha dpc function work\n");
  151. KeSetEvent(&device_extension->request_event,
  152. (KPRIORITY) 0,
  153. FALSE);
  154. };
  155. NTSTATUS ThreadFunc ( IN PVOID Context)
  156. {
  157. PFILE_OBJECT ConnectionFileObject, AddressFileObject;
  158. HANDLE AddressHandle, ConnectionHandle;
  159. NTSTATUS Status;
  160. IO_STATUS_BLOCK IoStatus;
  161. KEVENT Event;
  162. PDEVICE_OBJECT device_object;
  163. PDEVICE_EXTENSION device_extension;
  164. device_object = (PDEVICE_OBJECT) Context;
  165. device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
  166. KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
  167. //****************************
  168. //****************************
  169. //开始工作 此处用2重循环,你可以添加实际的代码
  170. for (;;)
  171. {
  172. do
  173. {
  174. dprintf("thread work ok !!\n");
  175. goto failselabel;
  176. } while (TRUE);
  177. failselabel:
  178. KeWaitForSingleObject(
  179. &device_extension->request_event,
  180. Executive,
  181. KernelMode,
  182. FALSE,
  183. NULL
  184. );//在这儿等
  185. //KeClearEvent(&Event);//清除一下试试
  186. //killvxk 2007-01-31 11:18
  187. //严重提醒不要使用KeClearEvent(&Event);
  188. //如果你还要用那个事件就不要用那个Clear,要其它手段~如果你不需要那个event了,
  189. //那你应该在thread里判断下~
  190. KeResetEvent(&device_extension->request_event);
  191. if ( device_extension->terminate_thread )
  192. {
  193. PsTerminateSystemThread(STATUS_SUCCESS);
  194. }
  195. }
  196. dprintf("never be here !\n");
  197. return Status;
  198. }
  199. VOID
  200. DriverUnload(
  201. PDRIVER_OBJECT pDriverObj
  202. )
  203. {
  204. PDEVICE_EXTENSION device_extension;
  205. UNICODE_STRING strLink;
  206. RtlInitUnicodeString(&strLink, LINK_NAME);
  207. device_extension = (PDEVICE_EXTENSION) pDriverObj->DeviceObject->DeviceExtension;
  208. //停止创建的线程
  209. if (KeCancelTimer(&device_extension->my_timer) == FALSE)
  210. {
  211. // KeCancelTimer(&device_extension->my_timer);//取消定时器
  212. dprintf( " no timer active at terminate\n");
  213. }
  214. device_extension->terminate_thread = TRUE;//停止线程
  215. KeSetEvent(
  216. &device_extension->request_event,
  217. (KPRIORITY) 0,
  218. FALSE
  219. );
  220. KeWaitForSingleObject(
  221. device_extension->thread_pointer,//等待线程对象结束,注意哦,是对象
  222. Executive,
  223. KernelMode,
  224. FALSE,
  225. NULL
  226. );
  227. ObDereferenceObject(device_extension->thread_pointer);
  228. IoDeleteSymbolicLink(&strLink);
  229. IoDeleteDevice(pDriverObj->DeviceObject);
  230. dprintf("[hello] Unloaded\n");
  231. }
  232. NTSTATUS
  233. DispatchCreate(
  234. PDEVICE_OBJECT pDevObj,
  235. PIRP pIrp
  236. )
  237. {
  238. pIrp->IoStatus.Status = STATUS_SUCCESS;
  239. pIrp->IoStatus.Information = 0;
  240. dprintf("[hello] IRP_MJ_CREATE\n");
  241. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  242. return STATUS_SUCCESS;
  243. }
  244. NTSTATUS
  245. DispatchClose(
  246. PDEVICE_OBJECT pDevObj,
  247. PIRP pIrp
  248. )
  249. {
  250. pIrp->IoStatus.Status = STATUS_SUCCESS;
  251. pIrp->IoStatus.Information = 0;
  252. dprintf("[hello] IRP_MJ_CLOSE\n");
  253. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  254. return STATUS_SUCCESS;
  255. }
  256. NTSTATUS
  257. DispatchIoctl(
  258. PDEVICE_OBJECT pDevObj,
  259. PIRP pIrp
  260. )
  261. {
  262. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  263. PIO_STACK_LOCATION pIrpStack;
  264. ULONG uIoControlCode;
  265. PVOID pIoBuffer;
  266. ULONG uInSize;
  267. ULONG uOutSize;
  268. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  269. uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  270. pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  271. uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  272. uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  273. switch(uIoControlCode) {
  274. case IOCTL_HELLO: {
  275. dprintf("[hello] Hello\n");
  276. status = STATUS_SUCCESS;
  277. }
  278. break;
  279. }
  280. if(status == STATUS_SUCCESS)
  281. pIrp->IoStatus.Information = uOutSize;
  282. else
  283. pIrp->IoStatus.Information = 0;
  284. /
  285. pIrp->IoStatus.Status = status;
  286. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  287. return status;
  288. }
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP