对 Windows驱动开发技术详解 第十章的(定时器)自我理解
BY:ALALMN—飞龙 QQ:316118740 BLOG:http://hi.baidu.com/alalmn
本章主要介绍DDK中Time(时间)循环的处理 很好很重要这里
I/O定时器最小间隔为1s,但是比较简单。
DPC定时器最小间隔为ms,但用法比I/O定时器复杂
///
I/O定时器(每间隔1s钟系统会调用一次I/O定时器例程)
初始化I/O定时器使用内核函数IoInitializeTimer
NTSTATUS
IoInitializeTimer(
IN PDEVICE_OBJECT DeviceObject, //这个参数是I/O定时器关联的设备对象指针
IN PIO_TIMER_ROUTINE TimerRoutine, //这个参数是I/O定时器关联的定时器例程
IN PVOID Context //这个参数是传入定时器例程的参数
);
开启定时器函数是IoStartTimer
停止定时器函数是IoStopTimer
///
DPC定时器
初始化定时器对象内核函数
VOID
KeInitializeTimer(
IN PKTIMER Timer //定时器指针
);
初始化DPC对象的内核函数
VOID
KeInitializeDpc(
IN PRKDPC Dpc, //这个参数是初始化的DPC对象指针
IN PKDEFERRED_ROUTINE DeferredRoutine, //这个参数是与DPC关联的DPC例程。每当定时器间隔倒时,操作系统就会将一个DPC对象插入队列,并触发该DPC例程运行。
IN PVOID DeferredContext //这个参数是传入DPC例程的参数
);
开启定时器的内核函数
BOOLEAN
KeSetTimer(
IN PKTIMER Timer, //这个参数是定时器对象指针
IN LARGE_INTEGER DueTime, //这个参数设定时间间隔
IN PKDPC Dpc OPTIONAL //这个参数是传入DPC例程的参数
);
取消定时器的内核函数
BOOLEAN
KeCancelTimer(
IN PKTIMER Timer //这个参数是定时器对象指针
);
///
等待
一,使用KeWaitForSingleObject函数。等待内核同步对象,但是也可以用来等待一段时间。
二,使用KeDelayExecutionThread函数。该内核函数和KeWaitForSingleObject类似,都是强制当前线程进入睡眠状态。经过指定的睡眠时间后,线程恢复运行。
三,使用KeStallExecutionProcessor函数。该内核函数是让CPU处于忙等待状态,而不是处于睡眠。经过指定时间后,继续让线程运行。
四,使用定时器
///
时间相关的其他内核函数
获取当前系统时间
VOID
KeQuerySystemTime(
OUT PLARGE_INTEGER CurrentTime //这个参数返回当前系统时间,以格林尼治时间计算。
);
将系统时间转化为当前时区对应的时间。
VOID
ExSystemTimeToLocalTime(
IN PLARGE_INTEGER SystemTime, //这个参数输入系统时间,以格林尼治时间为准。
OUT PLARGE_INTEGER LocalTime //这个参数是当前时区的时间。
);
将当前时间转化为系统时间,即格林尼治时间。
VOID
ExLocalTimeToSystemTime(
IN PLARGE_INTEGER LocalTime, //这个参数输入的当前时区时间。
OUT PLARGE_INTEGER SystemTime //这个参数输入系统时间,以格林尼治时间为准。
);
可以由当前的年月日得到系统时间
BOOLEAN
RtlTimeFieldsToTime(
IN PTIME_FIELDS TimeFields, //这个参数是输入的年月日等信息。
IN PLARGE_INTEGER Time //这个参数输出转换的系统时间
);
输入的TimeFields 是一个PTIME_FIELDS的数据结构,记录年月日等信息。
typedef struct TIME_FIELDS {
CSHORT Year; //年,最小取值1601
CSHORT Month; //月,取值范围是1到12
CSHORT Day; //日期,取值范围是1到31
CSHORT Hour; //小时,取值范围是0到23
CSHORT Minute; //分钟,取值范围是从0到59
CSHORT Second; //s,取值范围是从0到59
CSHORT Milliseconds; //ms,取值范围是从0到999
CSHORT Weekday; //礼拜几,取值范围是从0到6,代表周日到周六
} TIME_FIELDS;
//显示年月日等信息
KdPrint(("Current 年:%d/n",current_time_info.Year));
KdPrint(("Current 月:%d/n",current_time_info.Month));
KdPrint(("Current 日期:%d/n",current_time_info.Day));
KdPrint(("Current 小时:%d/n",current_time_info.Hour));
KdPrint(("Current 分钟:%d/n",current_time_info.Minute));
KdPrint(("Current S:%d/n",current_time_info.Second));
KdPrint(("Current MS:%d/n",current_time_info.Milliseconds));
KdPrint(("Current 星期:%d/n",current_time_info.Weekday));
将系统时间得到是具体月日年登信息
VOID
RtlTimeToTimeFields(
IN PLARGE_INTEGER Time, //这个参数是输入的系统时间
IN PTIME_FIELDS TimeFields //这个参数返回月日年信息,由TIME_FIELDS数据结构表示
);
///