对于NDIS miniport驱动而言,在完成了初始化历程之后,最关键的两个部分就是接收函数和发送函数。在windows环境之下,一般采用硬件中断的方式进行数据的接收。即,硬件在接收到数据之后,发起一个硬件中断,驱动在ISR中确认中断,并在Dpc中完成对数据的接收拷贝。
在驱动的开发过程中,出现了一个非常让人困惑的问题:在接收过程中会出现黑屏现象。一般来讲,黑屏的产生多是对内存的读写出现了问题。在缺少调试手段的情况下,想要确认问题的所在很麻烦,因为,他不像蓝屏,会生成dump文件供我们分析。
经过很久的分析,我才发现,问题出现在NdisMIndicateReceivePacket这个函数上面。通过阅读微软的函数说明文档,我们知道这个函数是用来向上层提交接收到的数据包的。在屏蔽掉这段代码之后,就不会出现黑屏现象。
思考了很久,在我觉得对这个函数的调用没有问题的情况下,我翻阅了ReactOS中对这个函数的实现。我发现了两点问题:
在这个函数的内部,存在一个自旋锁
这个函数会判断packet的状态时success还是resource
所以,很明显,一方面,我们在使用这个函数之前必须要释放掉自旋锁,另一方面必须要在接收拷贝数据包之后,使用NDIS_SET_PACKET_STATUS将packet的状态设为NDIS_STATUS_RESOURCES。按照相关书籍的说法:
若miniport驱动程 序 在 指 明 包 描 述 符 之 前 将 Status 成 员 设 为 NDIS_STATUS_RESOURCES , 则 它 在NdisMIndicateReceivePacket 返 回 之 后 ,应 当 立即 收 回 包描 述符 。
若 微 端 口 驱 动 程 序 在 指 明 包 描 述 符 之 前 将 包 的 Status 成 员 设 为NDIS_STATUS_SUCCESS , 则 微 端 口 驱 动 程 序 在 NDIS 将 包 描 述 符 返 回 给 微 端 口 驱 动 程 序 的MiniportReturnPacket 之前,不能收回包描述符。
在这样改动之后,黑屏现象暂时没有出现过了。