1.DPC(延迟过程调用)
DPC有普通的(normal) 和线程的(threaded)。普通的DPC可以在任何一个线程环境中运行,线程的DPC只能在一个专门的DPC线程中运行。
WRK 中DPC对象定义:
typedef struct _KDPC {
UCHAR Type;
UCHAR Importance;
UCHAR Number;
UCHAR Expedite;
LIST_ENTRY DpcListEntry;
PKDEFERRED_ROUTINE DeferredRoutine;
PVOID DeferredContext;
PVOID SystemArgument1;
PVOID SystemArgument2;
PVOID DpcData;
} KDPC, *PKDPC, *PRKDPC;
Type 说明DPC的对象类型,可能未DpcObject 或ThreadedDpcObject。
Importance 说明了一个DPC对象的重要程度,可以为低(LowImportance)、中(MediumImportance)或高(HighImportance)。当重要程度为高时,DPC对象被插入到DPC链表的头部,否则插入到尾部。
Number 指明DPC对象的目标处理器。
Expedite 保留成员。
DpcListEntry 是DPC对象加入到DPC链表中的节点对象。
DeferredRoutine 是真正被延迟执行的函数指针。
DeferredContext 可以指向任意数据结构,在DPC对象初始化时指定。
SystemArgument1、SystemArgument2 是延迟函数被执行时的两个参数。
DPCData 记录了它被插入到哪个DPC链表中。
根据在插入时是否触发软件中断,DPC对象在以下三种情况下被交付:
- 当处理器的IRQL从DISPATCH_LEVEL或更高级别降低到APC_LEVEL 或PASSIVE_LEVEL时,内核开始处理该处理器的DPC链表中的DPC对象,依次调用链表中DPC对象的延迟函数,直到链表为空。
- 通过KeInsertQueueDpc 插入DPC对象时。
- 在各个处理器的空闲线程中,如果发现有DPC对象尚未被执行,则交付这些DPC对象。
DPC流程,如图:
2.时钟中断和定时器管理
Windows 中最底层的定时器机制时通过时钟中断加上DPC对象来实现的。
系统中所有的定时器构成了一个链表数组,全局数组KiTimerTableListHead 包含了512个定时器链表,每个链表都有一个时间值,链表中的定时器为KTIMER对象。相关定义如下:
#define TIMER_TABLE_SIZE 512
typedef struct _KTIMER_TABLE_ENTRY {
LIST_ENTRY Entry;
ULARGE_INTEGER Time;
} KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY;
extern DECLSPEC_CACHEALIGN KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
typedef struct _KTIMER {
DISPATCHER_HEADER Header;
ULARGE_INTEGER DueTime;
LIST_ENTRY TimerListEntry;
struct _KDPC *Dpc;
LONG Period;
} KTIMER, *PKTIMER, *PRKTIMER;
DueTime :指定的到期时间
Windows的定时器管理结构,如图: