DPC,时钟中断,以及DPC定时器(1)

来源:互联网 发布:佣兵天下的java游戏 编辑:程序博客网 时间:2024/05/01 14:27

一、DPC

DPC IRQL高于软件中断 低于硬件中断,硬中断之后,用来完成需要延迟处理的额外操作(当然你也可以用来干别的,比如指定运行某个函数的cpu)

存储于KPRCB中,在wrk中是一个有两项的KDPC_DATA数组(多处理器中)

一个是普通的DPC,一个是针对指定线程的DPC(KiExecuteDpc 这个线程优先级最高 0)


typedef struct _KDPC_DATA {    LIST_ENTRY DpcListHead;    KSPIN_LOCK DpcLock;    volatile ULONG DpcQueueDepth;    ULONG DpcCount;} KDPC_DATA, *PKDPC_DATA;typedef struct _KDPC {    UCHAR Type;    UCHAR Importance;         重要的会插在头部,否则插在尾部    UCHAR Number;              插入的目标处理器    UCHAR Expedite;                LIST_ENTRY DpcListEntry;    挂入的链表    PKDEFERRED_ROUTINE DeferredRoutine;      DPC函数指针    PVOID DeferredContext;                                     函数的变量    PVOID SystemArgument1;    PVOID SystemArgument2;    PVOID DpcData;               记录插入哪个链表中} KDPC, *PKDPC, *PRKDPC;KeInsertQueueDpc前面是中规中矩的找cpu 的kpcr 然后找 相应的链表 直到                if (CurrentPrcb != TargetPrcb) { //如果是其他CPU                    if (((Dpc->Importance == HighImportance) ||                         (DpcData->DpcQueueDepth >= TargetPrcb->MaximumDpcQueueDepth))) {// 高度重要或者DPC超过指定数目                           if (((KiIdleSummary & AFFINITY_MASK(Number)) == 0) ||                            (KeIsIdleHaltSet(TargetPrcb, Number) != FALSE)) {                               TargetPrcb->DpcInterruptRequested = TRUE;             //请求DISPATCH_LEVEL的软中断                            RequestInterrupt = TRUE;                        }                    }                   } else { //当前CPU                    if ((Dpc->Importance != LowImportance) ||                        (DpcData->DpcQueueDepth >= TargetPrcb->MaximumDpcQueueDepth) ||                        (TargetPrcb->DpcRequestRate < TargetPrcb->MinimumDpcRate)) {                           TargetPrcb->DpcInterruptRequested = TRUE;                        RequestInterrupt = TRUE;                    }                }

DPC的处理时机是:1 DISPATCH_LEVEL以上级别降到APC级别或者以下时,处理DPC的请求(KiDispatchInterrupt(这个函数实在HalEndSystemInterrupt中被调用,处理软件中断结束)调用,)

   2 cpu的空闲线程来处理(KiIdleLoop调用)

DPC有自己的堆栈,在KPCR中保存了指针,在调用KiRetireDpcList之前要切换堆栈(与中断不同)

KiRetireDpcList逻辑非常简单,先处理DPC定时器 再处理DPC链表中的dpc请求。


原创粉丝点击