驱动开发中,与SetTimer()对应的函数是KeSetTimer():
BOOLEAN KeSetTimer(
_Inout_ PKTIMER Timer, ///---定时器
_In_ LARGE_INTEGER DueTime, ///---延后执行的时间
_In_opt_ PKDPC Dpc ///---要执行的回调函数结构
);
定时器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);
}