NDIS网络驱动程序学习(二)---NDIS协议驱动
什么是NDIS驱动呢?符合微软NDIS规范的,被NDIS管理器所管理的驱动程序,我们就叫它NDIS驱动。而NDIS协议驱动就是其中的一种类型。
所谓的符合NDIS规范的意思就是,你在编程的时候,要符合特定的编程规范,比如使用NDIS开头的API函数等等。那么如何才能接受NDIS管理器的管理呢?很简单,你只要注册就成了。注册的目的就是告诉操作系统,我这个驱动就是NDIS协议驱动了,以后呢,需要你NDIS管理器多多关照。和I/O管理器理解是一样的。
现在开始代码的分析部分。以寒江独钓里的代码为主。
在DriverEntry里的代码比较简单,一共做了2个比较重要的事情。
1,注册了一个设备,并指定了分发函数,这样为应用层留下了控制此驱动程序的机会。
2,注册自身为NDIS协议驱动。 现在分析具体细节
protocolChar.MajorNdisVersion
= 5;
protocolChar.MinorNdisVersion
= 0;
protocolChar.Name
= protoName;
protocolChar.OpenAdapterCompleteHandl
er
= NdisProtOpenAdapterCompl
ete;
protocolChar.CloseAdapterCompleteHand
ler = NdisProtCloseAdapterComp
lete;
protocolChar.SendCompleteHandler
= NdisProtSendComplete;
protocolChar.TransferDataCompleteHand
ler = NdisProtTransferDataComp
lete;
protocolChar.ResetCompleteHandler
= NdisProtResetComplete;
protocolChar.RequestCompleteHandler
= NdisProtRequestComplete;
protocolChar.ReceiveHandler
= NdisProtReceive;
protocolChar.ReceiveCompleteHandler
= NdisProtReceiveComplete;
protocolChar.StatusHandler
= NdisProtStatus;
protocolChar.StatusCompleteHandler
= NdisProtStatusComplete;
protocolChar.BindAdapterHandler
= NdisProtBindAdapter;
protocolChar.UnbindAdapterHandler
= NdisProtUnbindAdapter;
protocolChar.UnloadHandler
= NULL;
protocolChar.ReceivePacketHandler
= NdisProtReceivePacket;
protocolChar.PnPEventHandler = NdisProtPnPEventHandler;
上面这一堆,是我们需要关心的,说明如下:(讲解顺序是乱的,也必须乱)
1,告诉系统,本协议驱动使用的是哪个版本的NDIS,可以发现,我们现在使用的是5.0版本。需要说明的是,不同版本的回调函数并不相同,上面列举的回调函数是5.0版本所规定的。但是呢,高版本的NDIS管理器是支持低版本的NDIS驱动的,因此完全没有必要担心5.0的驱动不能用在6.0版本的NDIS系统上。
2,BindAdapterHandler:这个回调函数在什么时候调用呢?当一个真实网卡插入电脑后被小端口驱动识别并生成了一个“网卡设备”的时候,或者小端口驱动生成了一个“虚拟网卡设备”后,NDIS管理器调用这个回调函数来让NDIS协议驱动有机会来绑定被小端口驱动创建的“网卡设备”。以后呢,我们会称呼这些“网卡设备”为“实例”。
3,OpenAdapterCompleteHandler:当一个“实例”出现后,协议驱动都会去绑定它,那么很明显,绑定操作也是有个过程的,而系统内部很多时候都是异步模式。这个回调函数的作用就是:当协议驱动调用NdisOpenAdapter来进行绑定后,当绑定成功了,NDIS管理器会调用这个回调函数来通知此协议驱动已经绑定完成。
4,SendCompleteHandler:在协议驱动中可以调用NdisSendPackets来进行对数据包的发送。那么,发送数据包也是会有个过程的,和上面理解是一样的,此回调也是作为完成通知存在的。为什么没有发送回调呢?呵呵,发送操作本来就是“主动”的。没有必要和意义存在所谓的发送回调!
5,NdisProtCloseAdapterComplete:同理,当协议驱动调用NdisCloseAdapter来解除绑定的时候,作为解除成功的通知,此回调函数必须存在。
6,ReceiveHandler和ReceivePacketHandler:当NDIS管理器发现小端口“实例”有数据包到来了,那么这2个函数就会被调用。至于调用哪一个,下面详细分析。
7,UnbindAdapterHandler:当机器上一个物理网卡被拔出,或者小端口生成的“虚拟网卡”被消除,那么NDIS管理器会调用此回调函数来让协议驱动有机会来解除对这个网卡实例的绑定。通常,这个回调函数里会调用NdisCloseAdapter。并且呢,当解除绑定成功后,NDIS还会调用NdisProtCloseAdapterComplete来让协议驱动知道已经解除绑定成功。
8,其他的一些回调理解起来并不那么难,以后在分析具体的代码的时候再进行分析。
等把这些回调函数一个个的指定好了之后,我们就可以调用NdisRegisterProtocol了。此函数的作用非常重要,从效果上讲,他能够注册本驱动为NDIS协议驱动,从而可以接受NDIS管理器的管理和服务。从内部实现方面讲:此函数会在内核中创建一个非常重要的数据结构并记录下这些回调函数的地址,以后方便NDIS管理器调用。这和普通的Driver_Object理解上是相似的。
以后谈及NDIS过滤驱动的时候,你还会发现,一个驱动程序对应这3个重要的结构:普通的驱动结构,NDIS协议驱动结构,NDIS小端口驱动结构。而这些结构里都包含自己的一套回调函数,分别是:普通的分发函数,NDIS协议特征回调函数,NDIS小端口特征回调函数。而我们要做的就是好好理解透彻这些回调是如何协同工作的。一旦这些理解了,NDIS也就不难了。
下节继续
NDIS协议驱动