DPC分析 基于ReactOS0.33
来源:互联网 发布:淘宝店如何加入返利网 编辑:程序博客网 时间:2024/06/13 20:14
windows的过程,有如linux的软中断。以前Linux内核中自旋锁同步分析提到过,Linux通过IN_HARDIRQ/IN_SOFTIRQ来屏蔽软中断的执行,windows其实也类似,偷梁换柱的用IRQL来代替这些概念:IRQL高于DPC_LEVEL时,DPC过程无法执行,因为可能是中断过程正在执行;当通过KfLowerIrql降低IRQL请求级别到DPC_LEVEL及以下时开始执行DPC过程。降的再狠点,降到APC_LEVEL之下,还能执行APC请求。
ReactOS中关于DPC的执行流程相比与其他模块极其简单,因此本文只罗列大概流程,并不贴出代码。首先关于DPC对象的产生,设备对象初始化时可能会调用KiInitializeDpc,该函数仅仅设置执行DPC的过程和相应的参数,然后就结束了。设备对象可能会把该Dpc对象保存在自己的设备扩展部中,供以后使用。以后是指什么?当然是指发生中断而进入中断处理函数时,会调用KeInsertQueueDpc把Dpc对象插入到CPU控制模块Prcb!DpcData队列:
KDPC对象
typedef struct _KDPC{ UCHAR Type; UCHAR Importance; USHORT Number; LIST_ENTRY DpcListEntry; PKDEFERRED_ROUTINE DeferredRoutine; PVOID DeferredContext; PVOID SystemArgument1; PVOID SystemArgument2;//指向所挂入的KDPC_DATA结构,Prcb//上有两个KDPC_DATA(DPC)请求队列,一个是//普通的一个是DPC线程化的 volatile PVOID DpcData;} KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC;KeInsertQueueDpc代码片段:
KeRaiseIrql(HIGH_LEVEL, &OldIrql);CurrentPrcb = KeGetCurrentPrcb();//获得当前CPU的Prcb.../* 从Prcb的两个DpcData队列中选一个,将请求的Dpc挂到其中 */ /* Check if this is a threaded DPC and threaded DPCs are enabled */ if ((Dpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable)) { /* Then use the threaded data */ DpcData = &Prcb->DpcData[DPC_THREADED]; } else { /* Otherwise, use the regular data */ DpcData = &Prcb->DpcData[DPC_NORMAL]; }...KiAcquireSpinLock(&DpcData->DpcLock);//同个CPU的互斥,因为要插入队列..Dpc->SystemArgument1 = SystemArgument1; Dpc->SystemArgument2 = SystemArgument2; DpcData->DpcQueueDepth++; DpcData->DpcCount++; DpcConfigured = TRUE; /* Check if this is a high importance DPC */ if (Dpc->Importance == HighImportance) { /* Pre-empty other DPCs */ InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry); } else { /* Add it at the end */ InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry); }//插入队列结束,释放互斥锁KiReleaseSpinLock(&DpcData->DpcLock);...//最后发出DPC请求,当然DPC不会立马得到执行/* 正式发出请求,等到cpu从高IRQL降到DPC以下时, 内核扫描并执行队列中的DPC函数,如处理完 中断后调用KfLowerIrql时,据说扫描并执行DPC队列 也是线程切换的时机,这么说KiSwapContext是在DPC级别的 切换完了,IRQL再降级,才有机会执行APC */ HalRequestSoftwareInterrupt(DISPATCH_LEVEL);DPC的产生和请求都有了,那什么时候才是投递执行的时候?前面说了要等到IRQL下降,一般由调用者主动调用KfLowerIrql降低IRQL,借此机会DPC过程得以执行.
KfLowerIrql的内部实现是HalpLowerIrql,所以有必要进去浏览一下:
VOID HalpLowerIrql(KIRQL NewIrql, BOOLEAN FromHalEndSystemInterrupt){//执行Dpc/线程切换/Apc/的大好时机 ULONG Flags; UCHAR DpcRequested; if (NewIrql >= DISPATCH_LEVEL) { KeSetCurrentIrql (NewIrql); APICWrite(APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI); return; } Ke386SaveFlags(Flags); if (KeGetCurrentIrql() > APC_LEVEL) { KeSetCurrentIrql (DISPATCH_LEVEL); APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI); DpcRequested = __readfsbyte(FIELD_OFFSET(KIPCR, HalReserved[HAL_DPC_REQUEST])); if (FromHalEndSystemInterrupt || DpcRequested) { //以前在中断处理中发出的Dpc请求,现在要关闭 __writefsbyte(FIELD_OFFSET(KIPCR, HalReserved[HAL_DPC_REQUEST]), 0); _enable(); //投递Dpc KiDispatchInterrupt(); if (!(Flags & EFLAGS_INTERRUPT_MASK)) { _disable(); }} KeSetCurrentIrql (APC_LEVEL); } if (NewIrql == APC_LEVEL) { return; } if (KeGetCurrentThread () != NULL && KeGetCurrentThread ()->ApcState.KernelApcPending) { //投递APC _enable(); KiDeliverApc(KernelMode, NULL, NULL); if (!(Flags & EFLAGS_INTERRUPT_MASK)) { _disable(); } } KeSetCurrentIrql (PASSIVE_LEVEL);}投递Dpc还是在KiDispatchInterrupt中完成。这里有个疑问,希望路过的大神解答就是:ReactOS处理中断用了线程的堆栈,而处理Dpc使用Dpc专用堆栈,据说说linux中断处理过程没有进程的上下文,莫非linux中断用的是tss中设置的esp0?
这个函数,除了执行dpc还有一个重要的作用,切换线程
call @KiRetireDpcList@4...call @KiSwapContextInternal@0以前一直不知道线程切换是在哪个IRQL级别上,这回算是知道了~
最后KiRetireDpcList函数的实现很简单,就是如果有Dpc请求就遍历Prcb的Dpc队列,并执行其中的DPC过程。
0 0
- DPC分析 基于ReactOS0.33
- PNP管理器简析--基于ReactOS0.33
- windows内核情景分析 --- DPC
- DPC
- DPC
- ReactOS分析windows DPC机制(1)
- windows内核情景分析 --- DPC 目的信令点编码
- DPC函数
- DPC Timer
- DPC小记
- DPC定时器
- DPC计时器
- DPC定时器
- 阿里云产品分析(5):阿里云大数据处理工具DPC可用性分析与案例
- windows内核原理分析之DPC函数的执行(1)
- windows内核原理分析之DPC函数的执行(2)
- windows内核原理分析之DPC函数的执行(3)
- 分析驱动程序在IRQL>=DISPATCH_LEVEL时和DPC过程中不能用KeWaitForSingleObject等待对象的原因
- PLSQL Developer 连接Oracle 11g
- maven工程pom.xml文件讲解
- iOS开发系列--并行开发其实很容易
- Java加密技术介绍
- socket异步编程--libevent的使用
- DPC分析 基于ReactOS0.33
- 二叉树重建(衔接上一篇二叉树基本讲解)
- Property Animation 的使用
- 目标检测的图像特征提取之(二)LBP特征
- 关于低端外包
- C#加载滚动图片
- 教你怎么跳槽涨工资
- 简单学习STM32串口232
- P123.28