驱动开发中,与SetTimer()对应的函数是KeSetTimer():
BOOLEAN KeSetTimer( _Inout_ PKTIMER Timer,<span style="white-space:pre"> </span>///---定时器 _In_ LARGE_INTEGER DueTime,<span style="white-space:pre"> </span>///---延后执行的时间 _In_opt_ PKDPC Dpc<span style="white-space:pre"> </span>///---要执行的回调函数结构 );定时器Timer 和要 执行的 回调函数 结构Dpc 都必须先初始化,Timer的初始化比如 向下面这样:
KTIMER my_timer; KeInitalizeTimer(&my_timer);Dpc的初始化比较麻烦,因为需要一个回调函数。看看它的原型:
VOID KeInitializeDpc( _Out_ PRKDPC Dpc, _In_ PKDEFERRED_ROUTINE DeferredRoutine, _In_opt_ PVOID DeferredContext );PKDEFERRED_ROUTINE 这个函数指针类型所对应的函数类型实际上是这样的:
VOID CustomDpc( _In_ struct _KDPC *Dpc, _In_opt_ PVOID DeferredContext, _In_opt_ PVOID SystemArgument1, _In_opt_ PVOID SystemArgument2 ) { ... }我们只关心 DeferredContext。这个参数是KeInitalizeDpc 调用时传入的参数。用来提供给CustomDpc 被调用的时,让用户传入一些参数。
SystemArgument1 和 SystemArgument2 ,不需理会。
注意!!!! CustomDpc 函数将运行在APC中断级,因此并不是所有的事情都可以做。
下面的代码摘自<天书夜读-从汇编到Windows内核编程>,封装了定时器的需要全部信息。
typedef struct MY_TIMER_ { KDPC dpc; KTIMER timer; PKDEFERRED_ROUTINE func; //-回调函数 PVOID private_context; } MY_TIMER, *PMY_TIMER; ///--初始化 void MyTimerInit(PMY_TIMER timer, PKDEFERRED_ROUTINE func) { KeInitalizeDpc(&timer->dpc, sf_my_dpc_routine, timer); timer->func = func; KeInitalizeTimer(&timer->timer); return (wd_timer_h)timer; } BOOLEAN MyTimerSet(PMY_TIMER timer, ULONG msec, PVOID context) { LARGE_INTEGER due; ///---msc 是毫秒 timer->private_context = context; return KeSetTimer(&timer->timer, due, &mytimer->dpc); } //---停止运行 void MyTimerDestroy(PMY_TIMER timer) { KeCancelTimer(&timer->timer); }
void MyOnTimer( IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { ///----这传入的是上下文是timer结构,用来下次再启动延迟时调用 PMY_TIMER timer = (PMY_TIMER)deferredContext; ///---获得用户上下文 PVOID my_context = timer->private_context; //---这里做 OnTimer总要做的事儿。 /// ....... ///------再次调用。这里设置的是每1秒调用 MyTimerSet(timer, 1000, my_context); }