有关DPC的一些内容

有关DPC的一些内容

deferred procedure call (DPC) 延迟过程调用

dpc 主要是为了减少处于高 IRQL 的硬件中断处理的时间。
由于低 IRQL 的硬件中断不能中断 高 IRQL 的硬件中断处理。
而可能有些硬件的中断处理代码量比较大,花的时间比较多,会造成其他硬件中断的响应会等的时间比较长。
很有可能就是因为 时钟中断处理,非常非常频繁,代码量也比较多,可能会比较大的影响到其他硬件中断的响应,至于硬件中断响应比较慢可能会对不同的硬件造成什么结果,有待研究。

$ DPC 队列

整个系统只有一个 DPC 队列,至少对单cpu的系统是如此,对于多cpu系统有可能是一个cpu一个,有待验证。

这个队列是个 LIST_ENTRY 链表。

链表头在 pcr 的 +800 struct _LIST_ENTRY DpcListHead。
链的深度在 pcr 的 +808 uint32 DpcQueueDepth。

所有的 dpc 都链在这个链上。

链上的每项是个 KDPC 结构。

struct  _KDPC (sizeof=32)
+00 int16    Type
+02 byte    Number
+03 byte    Importance
+04 struct  _LIST_ENTRY DpcListEntry
+04    struct  _LIST_ENTRY *Flink
+08    struct  _LIST_ENTRY *Blink
+0c function *DeferredRoutine
+10 void    *DeferredContext
+14 void    *SystemArgument1
+18 void    *SystemArgument2
+1c uint32  *Lock

$ DPC 的源头

所有的 DPC 都是在 IRQL >= DISPATCH_LEVEL 的代码中产生的。
也就是只有 IRQL 大于等于 DISPATCH_LEVEL 的代码使用 DPC。

DPC 都是在硬件中断服务例程(ISR)中,由硬件中断服务例程根据自己的需要,链入到 DPC 队列中的。
中断服务例程中调用 KeInsertQueueDpc 将 dpc 链入 dpc 队列,或者,中断服务例程直接操作 dpc 链表,将 dpc 链入。

KeInsertQueueDpc 除了将 dpc 链入链之外,还会调用 KiRequestSoftwareInterrupt(DISPATCH_LEVEL),如果调用是的 IRQL 高于 DISPATCH_LEVEL,会使得 dpc pending,等到 irql 降下来的时候得到执行。

如果是自己直接操作链来将dpc链入的话,也需要自己调用类似 KiRequestSoftwareInterrupt(DISPATCH_LEVEL) 的函数。

$ DPC 的执行

在硬件中断处理的最后,会调用 HalEndSystemInterrupt。
HalEndSystemInterrupt 中,会将 IRQL 降低,然后检查是否有 DPC pending,有的话,会调用 KiDispatchInterrupt 处理 dpc。

KiDispatchInterrupt 中调用 KiRetireDpcList 处理 dpc。

也就是说,当在硬件中断处理中加入一个 dpc,那么当这个硬件中断处理结束的时候,就会调用这个被加入的 DPC。

a:所有处理都放在isr中
b:处理分两部分,必须要做的放在isr中,剩下的放在dpc中,isr中使用dpc

a的处理代码一直执行下来,只可能被irql比它高的硬件中断中断。
b的isr一直执行下来,紧接着执行dpc。isr部分只能被irql比它高的硬件中断中断。dpc部分可被任何硬件中断中断。

$ DPC 不可能受到线程切换的影响

会不会 DPC 中的代码执行到一半,发生线程切换,或者线程抢占,CPU 转去执行什么线程?
答案是绝对不会。

这是由于负责线程切换,抢占的代码就是运行在 IRQL DISPATCH_LEVEL,而 IRQL 小于等于当前 IRQL 的中断不能发生。
所以运行 dpc 时,irql 为 DISPATCH_LEVEL,根本就不会发生线程切换,线程抢占之类的事情。

当然中断中,就更不会了。

$ KiDispatchInterrupt

DISPATCH_LEVEL 上执行的代码有两大种,
一种是各种 isr 加的 dpc,处理一个 dpc,也就是调用这个 dpc 中的 DeferredRoutine。
一种是关于线程调度的。

KiDispatchInterrupt 是和 dpc 相关的重要函数。
KiDispatchInterrupt 主要做以下工作:

{
从 pcr 中得到 dpc 链表头。
如果链表不空的话,调用 KiRetireDpcList 处理 dpc。也就是一个一个的调用dpc里的 DeferredRoutine。

检查 pcr 中的 QuantumEnd,看是否为0。不为0进行 QuantumEnd 的处理。
检查 pcr 中的 NextThread,看是否为0。不为0进行 更换新的线程的 处理。
}

由于 KiDispatchInterrupt 会在各种硬件中断处理的结束有可能得到调用,当硬件中断处理过程中使用dpc的情况下就会在中断处理结束的时候被调用。

如果有任何代码使用 DISPATCH_LEVEL RequestSoftwareInterrupt 的话,KiDispatchInterrupt 也可能被立即执行。

QuantumEnd 不为0的情况,目前只有一种情况引起,就是时钟中断处理中,将当前线程的 Quantum 减少后,发现当前线程 Quantum 用完,就会设置 QuantumEnd,并在 时钟中断 处理结束的时候,引起 KiDispatchInterrupt 执行。

NextThread 不为0的情况,是哪些情况下引起的,还待研究。
 
DPC不产生中断,DPC是用于处理中断。中断处理分为两部分,类似于linux中的TopHalf和BottomHalf。如果中断处理很简单,在ISR中做就可以了,否则就要注册一个DPC,进行进一步的处理。 (这就是PDC在IRQL中处于仅次于硬件中断下最高级的一个原因,ps:apc在中断调度表中处于最低)

“内核利用DPC来处理定时器到期”---这里,定时器到期是什么意思?定时器又是什么?是不是和我们平时看到的定时器是一个概念?在哪本书能找到相关概念解释?
“并解除那些正在等待定时器的线程”----等待定时器?什么意思?线程为什么会等待定时器?什么个等待法?
“以及当一个线程的时限到期以后重新调度处理器”----线程的时限是啥东西?重新调度处理器,处理器的的调度什么理解?

处理器调度就是指线程调度
关于定时器:
Timer Objects and DPCs
Any driver can use a timer object within a nonarbitrary thread context to time out operations within the driver's other routines, or to perform a periodic operation. A driver calls KeInitializeTimer or KeInitializeTimerEx to set up a timer object.

A timer can be set to expire just once, or to expire repeatedly after a given interval. KeSetTimer always sets a timer that will expire just once. KeSetTimerEx accepts an optional Period parameter, which specifies a recurring timer interval.

An optional CustomTimerDpc routine (a type of deferred procedure call) can be associated with either a notification timer or a synchronization timer. This routine executes when the specified time interval expires. For more information, see Using Timer Objects.

A timer can be a notification timer or a synchronization timer.

When a notification timer is signaled, all waiting threads have their wait satisfied. The state of the timer remains signaled until it is explicitly reset.
When a synchronization timer expires, its state is set to Signaled until a single waiting thread is released. Then the timer is reset to the Not-Signaled state.
KeInitializeTimer always creates notification timers. KeInitializeTimerEx accepts a Type parameter, which can be NotificationTimer or SynchronizationTimer.

This section contains the following topics, which provide more information about timer objects and DPCs:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值