-
-
[旧帖] [求助]《WINDOW驱动开发技术详解》这本书里关于介绍StartIO处的几个问题 0.00雪花
-
发表于: 2012-8-31 22:24 1067
-
#pragma LOCKEDCODE VOID HelloDDKStartIO( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { KIRQL oldirql; KdPrint(("Enter HelloDDKStartIO\n")); //获取cancel自旋锁 ///////oldirql 是提出的问题1 ///////////////////// IoAcquireCancelSpinLock(&oldirql); ///////下面的/*Irp!=DeviceObject->CurrentIrp*/是 问题2///// /////////////////Irp->Cancel/////// 是问题3/////////// if (Irp!=DeviceObject->CurrentIrp||Irp->Cancel) { //如果当前有正在处理的IRP,则简单的入队列,并直接返回 //入队列的工作由系统完成,在StartIO中不用负责 IoReleaseCancelSpinLock(oldirql); KdPrint(("Leave HelloDDKStartIO\n")); return; }else { //由于正在处理该IRP,所以不允许调用取消例程 //因此将此IRP的取消例程设置为NULL IoSetCancelRoutine(Irp,NULL); IoReleaseCancelSpinLock(oldirql); } ////////////////////////////////////////////////////////////////////////////////////////
OnCancelIRP( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { KdPrint(("Enter CancelReadIRP\n")); if (Irp==DeviceObject->CurrentIrp) { //表明当前正在改由StartIo处理 //但StartIo并没有获取cancel自旋锁之前 //这时候需要 ///////关于oldirql = Irp->CancelIrql;关于这两个变量的代码是 问题4///////// KIRQL oldirql = Irp->CancelIrql; //释放Cancel自旋锁 IoReleaseCancelSpinLock(Irp->CancelIrql); IoStartNextPacket(DeviceObject,TRUE); KeLowerIrql(oldirql); }else { //从设备队列中将该IRP抽取出来 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,&Irp->Tail.Overlay.DeviceQueueEntry); //释放Cancel自旋锁 IoReleaseCancelSpinLock(Irp->CancelIrql); }
问题1:oldirql这个自旋锁,第一,是局部的变量,是不是起不到什么临界区的作用。
第二,就算他起到了自旋的用,可是 IoAcquireCancelSpinLock(&oldirql);不管获没获得到自旋锁,是不是都应该是继续执行下面的代码?是不是不像临界区那样直接就卡在这里了?那么一直到释放这个自旋锁为止,所有的代码并没有起到什么锁的作用啊?
问题2:Irp!=DeviceObject,这个判断有可能为真吗?StartIO是由IOStartPacket,和IOStartNextPacket两个函数触发,在P266页,两个函数的伪代码明明写的其内部在调用DriverStartIO值前已经将DeviceObject->CurrentIrp=Irp;然后调用StartIO.
这个问题我或许多少能猜到点,不知道对不对。假设StartIO刚进入例程代码,什么事还没干,有一个新的IRP产生,并在某派遣函数中调用IOStartPacket,和IOStartNextPacket两个函数,而这两个函数将DeviceObject->CurrentIrp=Irp(Irp为新的值了),因此StartIO函数代码里Irp!=DeviceObject,所以StartIO不去处理这个Irp是吗?感觉如果是这样代码有点没有效率,不过或许还有其他的操作会改变DeviceObject->CurrentIrp,如果StartIO不管这两个变量是否相等而去继续处理,会引发什么异常吧。
问题3:Irp->Cance这个变量我才开始一直以为是自旋锁,后来看看又不像,因为已经有了Irp->CancelIrql这个自旋锁了,所以这个Irp->Cance是不是取消例程的一个标志,就是标志取消例程正在运行?如果是这样能解释下,这个标志是再什么时间被赋值的吗?
问题4:
if (Irp==DeviceObject->CurrentIrp) { //表明当前正在改由StartIo处理 //但StartIo并没有获取cancel自旋锁之前 //这时候需要 KIRQL oldirql = Irp->CancelIrql; //释放Cancel自旋锁 IoReleaseCancelSpinLock(Irp->CancelIrql); IoStartNextPacket(DeviceObject,TRUE); KeLowerIrql(oldirql); }
第一,注释里说 /*//但StartIo并没有获取cancel自旋锁之前 */StartIo的代码里只有这个 IoAcquireCancelSpinLock(&oldirql);,难道自旋锁就一个吗?如果自旋锁就一个,我也没看出他起了什么锁的作用啊?而且假设我学错了,自旋锁就一个,那么参数oldirql也就没什么实际的用处了,直接就两个函数 一个获取(),一个释放(),不是更简单?加个参数有什么用?
第二,如果IRP的取消例程还没有运行,StartIO已经将这个IRP处理了,是不是最后的 IoCompleteRequest( Irp, IO_NO_INCREMENT );也会释放这个Irp->CancelIrql自旋锁?因为我在StartIO里再没看到这个IoReleaseCancelSpinLock(Irp->CancelIrql);的代码。
第三,KeLowerIrql(oldirql);这里是降低IRQL,这里又有点迷糊了,降低自旋锁等级是什么意思,求大侠解释下。
新手问题就是多,大侠别介意,有哪个大侠给解释下,我先碰头谢谢了,(磕头就不磕了,有点过,多碰几下吧)
谁能解答下,小弟真心真心的谢谢了
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: