Windows 驱动机制-定时、DPC及延时
2017-09-04 11:46
423 查看
1、定义Timer及DPC
typedef struct _DEVICE_EXTENSION {
.
.
.
KDPC Dpc;
KTIMER Timer;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
2、初始化Timer及DPC
LARGE_INTEGER DueTime;
DueTime.QuadPart=-10000*2000;//定时2秒
KeInitializeDpc(&deviceExtension->Dpc,CustomTimerDPC,deviceExtension);
KeInitializeTimer(&deviceExtension->Timer);
KeSetTimer(&deviceExtension->Timer,DueTime,&deviceExtension->Dpc);
3、DPC处理函数
void CustomTimerDPC (
IN PKDPC pDpc,
IN PVOID deferredContext,
IN PVOID systemArgument1,
IN PVOID systemArgument2
) {
PDEVICE_EXTENSION deviceExtension = NULL;
KIRQL OldIrql;
if (sizeof(deferredContext) != sizeof(PDEVICE_EXTENSION))
return;
deviceExtension = (PDEVICE_EXTENSION)deferredContext;
SKYDbgPrint (SKY_CHECK, ("Timeout"));
}
4、取消定时器
KeCancelTimer(&deviceExtension->Timer);
注:KeSetTimer的定时精度为15ms左右,如果要更高精度的定时,请用其它方法。DPC必须为经过KeInitializeDpc初始化后的DPC
内核延时:
方法一:NdisMSleep
VOID
NdisMSleep(
IN ULONG MicrosecondsToSleep
);
直接调用NdisMSleep,它的参数是微秒数量级。不过这里一定要注意
调用环境:
KeGetCurrentIrql < DISPATCH_LEVEL
方法二:NdisStallExecution
VOID
NdisStallExecution(
IN UINT MicrosecondsToStall
);
这里也是直接调用,参数是微秒级,但是最好不要用它延时超过50个微秒。
调用环境:
Any IRQL
MicrosecondsToStall <= 50
方法三:KeDelayExecutionThread
NTSTATUS
KeDelayExecutionThread(
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Interval
);
该函数将当前执行线程置于等待状态,当时间过后被唤醒。
调用环境:
KeGetCurrentIrql <= APC_LEVEL
参考代码:
LARGE_INTEGER liTime;
/* Convert milliseconds to 100-nanosecond increments using:
*
* 1 ns = 10 ^ -9 sec
* 100 ns = 10 ^ -7 sec (1 timer interval)
* 1 ms = 10 ^ -3 sec
* 1 ms = (1 timer interval) * 10^4
*/
delay = delay * 10000;
// Negative value means relative time, not absolute
liTime =
RtlConvertLongToLargeInteger(
-(LONG)delay
);
//Callers of KeDelayExecutionThread must be running at IRQL <= APC_LEVEL.
DbgPrint("KeGetCurrentIrql = %d\n", KeGetCurrentIrql());
KeDelayExecutionThread(
KernelMode,
TRUE,
&liTime
);
方法四:KeWaitForSingleObject
NTSTATUS
KeWaitForSingleObject(
IN PVOID Object,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL
);
该函数等待信号的到来,如果在所设时间之内没有信号,则返回TimeOut。
调用环境:
KeGetCurrentIrql <= PASSIVE_LEVEL
参考代码:
LARGE_INTEGER TimeoutTimer;
TimeoutTimer = RtlConvertLongToLargeInteger(
-(LONG)(delay * 10000)
);
//sleep,waiting (TimeoutWait) singaled
DbgPrint("KeGetCurrentIrql = %d\n", KeGetCurrentIrql());
status = KeWaitForSingleObject(
&TimeoutWait,
Executive,
KernelMode,
FALSE,
&TimeoutTimer
);
方法五:空循环
调用环境:
任何情况下都可使用。
参考代码:
LARGE_INTEGER liTime, startTime, currentTime;
/* Convert milliseconds to 100-nanosecond increments using:
*
* 1 ns = 10 ^ -9 sec
* 100 ns = 10 ^ -7 sec (1 timer interval)
* 1 ms = 10 ^ -3 sec
* 1 ms = (1 timer interval) * 10^4
*/
delay = delay * 10000;
KeQuerySystemTime(&startTime);
while(1){
KeQuerySystemTime(¤tTime);
liTime.QuadPart = currentTime.QuadPart - startTime.QuadPart;
if(liTime.QuadPart >= delay) break;
}
以上方法中前面四种不占用CPU时钟,第五种方法会占用CPU时钟,在迫不得已的情况下使用。
typedef struct _DEVICE_EXTENSION {
.
.
.
KDPC Dpc;
KTIMER Timer;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
2、初始化Timer及DPC
LARGE_INTEGER DueTime;
DueTime.QuadPart=-10000*2000;//定时2秒
KeInitializeDpc(&deviceExtension->Dpc,CustomTimerDPC,deviceExtension);
KeInitializeTimer(&deviceExtension->Timer);
KeSetTimer(&deviceExtension->Timer,DueTime,&deviceExtension->Dpc);
3、DPC处理函数
void CustomTimerDPC (
IN PKDPC pDpc,
IN PVOID deferredContext,
IN PVOID systemArgument1,
IN PVOID systemArgument2
) {
PDEVICE_EXTENSION deviceExtension = NULL;
KIRQL OldIrql;
if (sizeof(deferredContext) != sizeof(PDEVICE_EXTENSION))
return;
deviceExtension = (PDEVICE_EXTENSION)deferredContext;
SKYDbgPrint (SKY_CHECK, ("Timeout"));
}
4、取消定时器
KeCancelTimer(&deviceExtension->Timer);
注:KeSetTimer的定时精度为15ms左右,如果要更高精度的定时,请用其它方法。DPC必须为经过KeInitializeDpc初始化后的DPC
内核延时:
方法一:NdisMSleep
VOID
NdisMSleep(
IN ULONG MicrosecondsToSleep
);
直接调用NdisMSleep,它的参数是微秒数量级。不过这里一定要注意
调用环境:
KeGetCurrentIrql < DISPATCH_LEVEL
方法二:NdisStallExecution
VOID
NdisStallExecution(
IN UINT MicrosecondsToStall
);
这里也是直接调用,参数是微秒级,但是最好不要用它延时超过50个微秒。
调用环境:
Any IRQL
MicrosecondsToStall <= 50
方法三:KeDelayExecutionThread
NTSTATUS
KeDelayExecutionThread(
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Interval
);
该函数将当前执行线程置于等待状态,当时间过后被唤醒。
调用环境:
KeGetCurrentIrql <= APC_LEVEL
参考代码:
LARGE_INTEGER liTime;
/* Convert milliseconds to 100-nanosecond increments using:
*
* 1 ns = 10 ^ -9 sec
* 100 ns = 10 ^ -7 sec (1 timer interval)
* 1 ms = 10 ^ -3 sec
* 1 ms = (1 timer interval) * 10^4
*/
delay = delay * 10000;
// Negative value means relative time, not absolute
liTime =
RtlConvertLongToLargeInteger(
-(LONG)delay
);
//Callers of KeDelayExecutionThread must be running at IRQL <= APC_LEVEL.
DbgPrint("KeGetCurrentIrql = %d\n", KeGetCurrentIrql());
KeDelayExecutionThread(
KernelMode,
TRUE,
&liTime
);
方法四:KeWaitForSingleObject
NTSTATUS
KeWaitForSingleObject(
IN PVOID Object,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL
);
该函数等待信号的到来,如果在所设时间之内没有信号,则返回TimeOut。
调用环境:
KeGetCurrentIrql <= PASSIVE_LEVEL
参考代码:
LARGE_INTEGER TimeoutTimer;
TimeoutTimer = RtlConvertLongToLargeInteger(
-(LONG)(delay * 10000)
);
//sleep,waiting (TimeoutWait) singaled
DbgPrint("KeGetCurrentIrql = %d\n", KeGetCurrentIrql());
status = KeWaitForSingleObject(
&TimeoutWait,
Executive,
KernelMode,
FALSE,
&TimeoutTimer
);
方法五:空循环
调用环境:
任何情况下都可使用。
参考代码:
LARGE_INTEGER liTime, startTime, currentTime;
/* Convert milliseconds to 100-nanosecond increments using:
*
* 1 ns = 10 ^ -9 sec
* 100 ns = 10 ^ -7 sec (1 timer interval)
* 1 ms = 10 ^ -3 sec
* 1 ms = (1 timer interval) * 10^4
*/
delay = delay * 10000;
KeQuerySystemTime(&startTime);
while(1){
KeQuerySystemTime(¤tTime);
liTime.QuadPart = currentTime.QuadPart - startTime.QuadPart;
if(liTime.QuadPart >= delay) break;
}
以上方法中前面四种不占用CPU时钟,第五种方法会占用CPU时钟,在迫不得已的情况下使用。
相关文章推荐
- 第二十七篇:Windows驱动中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace
- 延时及定时机制
- Windows事件驱动机制及消息循环
- Winsocket入门教程三:以Windows消息机制驱动的客户端程序
- TCP的确认延时机制及Windows系统的确认延时修改
- TCP的确认延时机制及Windows系统的确认延时修改
- Windows事件驱动机制及消息循环
- 系统延时及定时机制
- Windows 消息处理机制与事件驱动
- [C++ VC MFC] Windows 的定时机制
- Linux 第六周学习笔记 (2),特殊权限列表,at延时任务及定时机制,系统临时文件的管理
- windows 的事件驱动机制和消息循环
- Windows 10新机制导致Android驱动失效
- Linux设备驱动之定时与延时
- windows中定时关闭并延时打开某个运行程序
- 如何延时Windows Embedded CE驱动的加载
- 系统延时及定时机制
- linux驱动之定时任务timer,队列queue,小任务tasklet机制及用法
- 模仿Windows的消息驱动机制获得了成功
- Windows 批处理实现 定时打开IE 延时一段时间后 关闭IE