内核模式下的定时器
好文章,来自【福优学苑@音视频+流媒体】
简介与章节概览:
Windows内核中的两种定时器:
A、I/O定时器
B、DPC定时器
Windows内核中的四种等待:
A、KeWaitForSingleObject
B、KeDelayExecutionThread
C、KeStallExecutionProcessor
D、DPC定时器等待
数据结构与API:
IoInitializeTimer(pDevObj,OnTimer,NULL);
IoStartTimer(...)
IoStopTimer(...)
KTIMER, KDPC(dpc回调例程)
KeInitializeTimer( &pDevExt->pollingTimer );
KeInitializeDpc( &pDevExt->pollingDPC,
PollingTimerDpc,//回调例程
(PVOID) pDevObj );
KeSetTimer(
&pDevExt->pollingTimer,
pDevExt->pollingInterval,
&pDevExt->pollingDPC );
KeCancelTimer(&pDevExt->pollingTimer);
定时器实现方式一
I/O定时器
IoInitializeTimer(pDevObj,OnTimer,NULL);
IoStartTimer(...)
IoStopTimer(...)
示例代码
#pragma LOCKEDCODE VOID OnTimer( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; KdPrint(("Enter OnTimer!\n")); //将计数器自锁减一 InterlockedDecrement(&pDevExt->lTimerCount); //如果计数器减到0,重新编程TIMER_OUT,整个过程是互锁运算 LONG previousCount = InterlockedCompareExchange(&pDevExt->lTimerCount,TIMER_OUT,0); //每隔三秒,计数器一个循环,输出以下log if (previousCount==0) { KdPrint(("%d seconds time out!\n",TIMER_OUT)); } //证明该线程运行在任意线程上下文的 PEPROCESS pEProcess = IoGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);//即可得到用户进程 KdPrint(("The current process is %s\n",ProcessName)); }
定时器实现方式二
DPC定时器
KTIMER, KDPC(dpc回调例程)
KeInitializeTimer( &pDevExt->pollingTimer ); KeInitializeDpc( &pDevExt->pollingDPC, PollingTimerDpc,//回调例程 (PVOID) pDevObj ); KeSetTimer( &pDevExt->pollingTimer, pDevExt->pollingInterval, &pDevExt->pollingDPC ); KeCancelTimer(&pDevExt->pollingTimer); 示例代码 #pragma LOCKEDCODE VOID PollingTimerDpc( IN PKDPC pDpc, IN PVOID pContext, IN PVOID SysArg1, IN PVOID SysArg2 ) { PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; KeSetTimer( &pdx->pollingTimer, pdx->pollingInterval, &pdx->pollingDPC ); KdPrint(("PollingTimerDpc\n")); //检验是运行在任意线程上下文 /////PEPROCESS pEProcess = IoGetCurrentProcess(); /////PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174); /////KdPrint(("%s\n",ProcessName)); }
等待
第一种方法:使用KeWaitForSingleObject
第二种方法:使用KeDelayExecutionThread
第三种方法:使用KeStallExecutionProcessor
第四种方法:使用DPC定时器
时间相关的其他内核函数
时间相关函数
KeQuerySystemTime(...)
ExSystemTimeToLocalTime
RtlTimeToTimeFields
示例代码
#pragma PAGEDCODE VOID Time_Test() { LARGE_INTEGER current_system_time; //得到当前系统时间 KeQuerySystemTime(¤t_system_time); LARGE_INTEGER current_local_time; //从系统时间转换成当地时区时间 ExSystemTimeToLocalTime(¤t_system_time,¤t_local_time); TIME_FIELDS current_time_info; //由当地时区时间得到月日年信息 RtlTimeToTimeFields(¤t_local_time,¤t_time_info); //显示年月日等信息 KdPrint(("Current year:%d\n",current_time_info.Year)); KdPrint(("Current month:%d\n",current_time_info.Month)); KdPrint(("Current day:%d\n",current_time_info.Day)); KdPrint(("Current Hour:%d\n",current_time_info.Hour)); KdPrint(("Current Minute:%d\n",current_time_info.Minute)); KdPrint(("Current Second:%d\n",current_time_info.Second)); KdPrint(("Current Milliseconds:%d\n",current_time_info.Milliseconds)); KdPrint(("Current Weekday:%d\n",current_time_info.Weekday)); }
IRP的超时处理
原理
示例代码
好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***