|
|
|
|
|
|
|
Windows内核调试
帖子发起人: Thomson 发起时间: 2008-09-02 23:35 下午 回复: 8
|
帖子排序:
|
|
|
|
2008-09-02, 23:35 下午
|
Thomson
注册: 2008-07-03
发 贴: 211
|
DPC是怎么执行到的呢
|
|
|
|
在设备的ISR里面可以扣队一个DPC,让中断时间不至于太长,当IRQL降到DPC level就可以执行. 那么IRQL降低应该只是set KPCR里面的一个变量,是什么机制保证了这个IRQL降低了后,DPC就被执行到呢?
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 08:41 上午
|
Coding
注册: 2008-05-31
发 贴: 103
|
|
|
简单来说,kernel queues a DPC时,其实是request了一个DISPATCH_LEVEL的软中断,当IRQL降低到小于DISPATCH_LEVEL时,中断被触发,这个中断级别的dispatcher被调用,并且执行在队列里面的每一个DPC object.
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 09:38 上午
|
王宇
注册: 2007-05-08
发 贴: 306
|
|
|
很复杂的问题... 我来抛块砖~
我认为具体的实现机制要根据不同的情况讨论,比如:DPC优先级的高低、是否在发出ISR的处理器上、TimerDPC等等。在同一处理器高/中优先级的DPC会直接触发DPC/Dispatch中断(即总是激发);在同一处理器低优先级的DPC需要等待阀值(队列长度);在不同处理器高优先级的DPC,内核会发出IPI通知其他CPU;而TimerDPC则是在nt!KiTimerListExpire()时call你的DPC例程(大致是nt!KiRetireDpcList-->nt!KiTimerExpiration-->nt!KiTimerListExpire()-->你的CustomTimerDPC),等等。
详细的语言描述可以参见Mark E. Russinovich的《Microsoft Windows Internals》3.1节“Trap Dispatching”
DPC priorities can affect system behavior another way. The kernel usually initiates DPC queue draining with a DPC/dispatch-level interrupt. The kernel generates such an interrupt only if the DPC is directed at the processor the ISR is requested on and the DPC has a high or medium priority. If the DPC has a low priority, the kernel requests the interrupt only if the number of outstanding DPC requests for the processor rises above a threshold or if the number of DPCs requested on the processor within a time window is low. If a DPC is targeted at a CPU different from the one on which the ISR is running and the DPC's priority is high, the kernel immediately signals the target CPU (by sending it a dispatch IPI) to drain its DPC queue. If the priority is medium or low, the number of DPCs queued on the target processor must exceed a threshold for the kernel to trigger a DPC/dispatch interrupt. The system idle thread also drains the DPC queue for the processor it runs on. Although DPC targeting and priority levels are flexible, device drivers rarely need to change the default behavior of their DPC objects. Table 3-1 summarizes the situations that initiate DPC queue draining.
特别是表3.1 它总结了DPC/Dispatch中断的产生规则,我这里就不列了。
关于代码实现要参看\ntos\ke\dpcsup.c,重要的有KiExecuteDpc()、KiRetireDpcList() / KiTimerExpiration() / KiTimerListExpire()。
另外要注意,Phase 1 的时候,PspInitPhase0() 创建了线程 Phase1Initialization() 而 Phase1Initialization() call 了 Phase1InitializationDiscard(),Discard里面的一个步骤是:
//
// Initialize OB, EX, KE, and KD.
//
if (!ObInitSystem()) {
KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
}
...
if (!KeInitSystem()) {
KeBugCheckEx(PHASE1_INITIALIZATION_FAILED,STATUS_UNSUCCESSFUL,0,2,0);
}
...
看 KeInitSystem() 的实现:
//
// If threaded DPCs are enabled for the host system, then create a DPC
// thread for each processor.
//
do {
Prcb = KiProcessorBlock[Index];
KeInitializeEvent(&Prcb->DpcEvent, SynchronizationEvent, FALSE);
InitializeListHead(&Prcb->DpcData[DPC_THREADED].DpcListHead);
KeInitializeSpinLock(&Prcb->DpcData[DPC_THREADED].DpcLock);
Prcb->DpcData[DPC_THREADED].DpcQueueDepth = 0;
Status = PsCreateSystemThread(&Handle,
THREAD_ALL_ACCESS,
&ObjectAttributes,
NULL,
NULL,
KiExecuteDpc,
Prcb);
if (!NT_SUCCESS(Status)) {
return FALSE;
}
注意PsCreateSystemThread()创建的KiExecuteDpc()。因为KiExecuteDpc()最后会Call the DPC routine:
//
// Call the DPC routine.
//
(DeferredRoutine)(Dpc,
DeferredContext,
SystemArgument1,
SystemArgument2);
OK~ 先写到这~
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 10:50 上午
|
Thomson
注册: 2008-07-03
发 贴: 211
|
|
|
谢谢楼上两位了,
不过我先在System里找start routine是nt!kiexecuteDpc的线程,没有找到,后来在virtual machine里面在nt!kiexecuteDpc上设置 breakpoint,然后启动virtual machine,也没有break到外面的windbg,
我觉得比较奇怪,如果是从这个方法对调用DPC routine的话,应该经常会break才对啊?
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 11:09 上午
|
王宇
注册: 2007-05-08
发 贴: 306
|
|
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 11:16 上午
|
Thomson
注册: 2008-07-03
发 贴: 211
|
|
|
我是server03的系统,内核是WRK的,
用x能解析到nt!kiexecutedpc
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 12:04 下午
|
王宇
注册: 2007-05-08
发 贴: 306
|
|
|
噢 那个是 threaded DPCs,
你实验可能需要下 nt!KiRetireDpcList 的断点。
nt!KiRetireDpcList 的代码片段:
//
// If the DPC list is not empty, then process the DPC list.
//
if (DpcData->DpcQueueDepth != 0) {
........
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 12:11 下午
|
王宇
注册: 2007-05-08
发 贴: 306
|
|
|
另,推荐一个DPC实验工具:
http://www.thesycon.de/deu/latency_check.shtml
还有一个微软的文章:
http://www.microsoft.com/whdc/driver/perform/mmdrv.mspx
http://www.microsoft.com/china/whdc/driver/perform/mmdrv.mspx
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-09-03, 12:35 下午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
|
|
WinDBG有个扩展命令!dpcs [CPU编号]用来显示DPC队列。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
高端调试 » 软件调试 » Windows内核调试 » Re: DPC是怎么执行到的呢
|
|
|
|
|
|