一、初始化 NDIS 定时器
任何NDIS驱动程序都可以有多个定时器,可以是一次性或周期性的。NDIS_TIMER_CHARACTERISTICS
结构定义了定时器的若干属性,其中一项是NetTimerCallback
函数入口。当定时器到期时,NDIS调用NetTimerCallback
函数执行定时任务。
- 初始化定时器:调用
NdisAllocateTimerObject
函数,传入自己定义的NDIS_TIMER_CHARACTERISTICS
结构 - 启动定时器:调用
NdisSetTimerObject
函数 - 释放定时器:调用
NdisFreeTimerObject
函数
其中,NdisAllocateTimerObject
函数原型为:
NDIS_STATUS NdisAllocateTimerObject(
_In_ NDIS_HANDLE NdisHandle,
_In_ PNDIS_TIMER_CHARACTERISTICS TimerCharacteristics,
_Out_ PNDIS_HANDLE pTimerObject
);
二、启动和清除定时器
利用NdisSetTimerObject
函数可令驱动程序在指定的时间间隔或定期之后触发定时任务函数,其函数原型为:
BOOLEAN NdisSetTimerObject(
_In_ NDIS_HANDLE TimerObject,
_In_ LARGE_INTEGER DueTime,
_In_opt_ LONG MillisecondsPeriod,
_In_opt_ PVOID FunctionContext
);
DueTime
参数指定计时器到期的绝对或相对时间。如果为负值,则到期时间是相对于当前系统时间;否则,到期时间是绝对的。到期时间以系统时间单位(100纳秒间隔)表示。绝对到期时间跟踪系统时间的任何变化;相对过期时间不受系统时间变化的影响。
MillisecondsPeriod
参数指定定时器的可选重复间隔(以毫秒为单位)。若大于或等于零,则定时器以该间隔周期性触发;若为零,则为非周期性定时器。(参考自 KeSetTimerEx 函数)
给出一些KeSetTimerEx
函数的示例:
LARGE_INTEGER duetime = {0};
#define POLLING_INTERVAL 3000
// KeSetTimer(&my_timer,timeout,&KiTimerExpireDpc); // 仅仅只能设置一次
// KeSetTimerEx(&my_timer, timeout, period, &KiTimerExpireDpc); // 这个可以循环设置
KeSetTimerEx(&device_extension->my_timer, duetime, POLLING_INTERVAL, &deviceEx->KiTimerDpc);
// KeSetTimerEx语句启动周期定时器。由于duetime参数是0,所以定时器立即进入信号态。然后每隔POLLING_INTERVAL=3秒触发一次。
调用NdisCancelTimerObject
函数可取消之前调用NdisSetTimerObject
函数设置的定时器。如果在调用NdisCancelTimerObject
之前定时已经到时,则NDIS可能仍会调用NetTimerCallback
。
关于NdisSetTimerObject
函数的更多信息,请参考 KeSetTimerEx 函数的介绍。
三、定时任务函数
定时器触发时,NDIS调用NetTimerCallback
函数,其函数原型为:
NDIS_TIMER_FUNCTION NdisTimerFunction;
void NdisTimerFunction(
PVOID SystemSpecific1,
PVOID FunctionContext,
PVOID SystemSpecific2,
PVOID SystemSpecific3
)
{...}
FunctionContext
参数指向驱动上下文,FunctionContext
的默认值在NDIS_TIMER_CHARACTERISTICS
结构中指定。值得注意的是,驱动在调用NdisSetTimerObject
函数时,仍可传入一个FunctionContext
参数。如此时传入了非 NULL 值,则该值会传给NetTimerCallback
函数;否则,将传入NDIS_TIMER_CHARACTERISTICS
结构中指定的默认值。
任何 NDIS 驱动程序都可以有多个NetTimerCallback
函数,每个这样的NetTimerCallback
函数都必须与不同的驱动程序初始化的定时器关联。
如果NetTimerCallback
函数与其他函数共享驱动资源,则应使用自旋锁来同步对这些资源的访问。
四、Microsoft 文档链接
- 数据结构:NDIS_TIMER_CHARACTERISTICS
- 调用函数:NdisAllocateTimerObject、NdisSetTimerObject、NdisCancelTimerObject、NdisFreeTimerObject
- 要实现的函数:NetTimerCallback
参考链接:
欢迎来我的 Git Pages 博客交流,本文最早发布于 http://hoxz.me/2018/04/22/ndis-timer-implement