内核模式下的定时器


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

简介与章节概览:


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(&current_system_time);
LARGE_INTEGER current_local_time;
//从系统时间转换成当地时区时间
ExSystemTimeToLocalTime(&current_system_time,&current_local_time);
TIME_FIELDS current_time_info;
//由当地时区时间得到月日年信息
RtlTimeToTimeFields(&current_local_time,&current_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的超时处理       

原理




示例代码


好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***