if( Sync ){/*处理与时间戳的同步发送*/<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

          

//如果需要阻塞超过约1秒,释放应用程序

           if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )

           {     

              //等待挂起的发送完成

              NPF_WaitEndOfBufferedWrite(Open);

              NPF_StopUsingBinding(Open);

              return (INT)((PCHAR)winpcap_hdr - UserBuff);

           }         

      

//计算在发送下一个数据包之前等待的时间间隔

           TargetTicks.QuadPart = StartTicks.QuadPart +

(LONGLONG)(

(winpcap_hdr->ts.tv_sec –

BufStartTime.tv_sec) * 1000000 +

winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *

(TimeFreq.QuadPart

)/1000000;

          

           //等待直到时间间隔逝去

           while( CurTicks.QuadPart <= TargetTicks.QuadPart )

              CurTicks = KeQueryPerformanceCounter(NULL);

       }  

    }

 

   

    NPF_StopUsingBinding(Open);

    //返回已发送的字节数

    return (INT)((PCHAR)winpcap_hdr - UserBuff);

}

函数PacketSendPackets通过NPF_IoControl函数调用NPF_BufferedWrite函数时需要考虑下列两个问题的处理:

Ø         数据包队列并不一定是一次全部传递给内核,可能分几次,所以NPF_BufferedWrite函数需要返回的字节大小需要进行头部对齐。

Ø         延迟时间的处理。

    PacketSendPacketsNPF_BufferedWrite两个函数中都能看见如下所示的类似的忙等待代码。

INT PacketSendPackets(LPADAPTER AdapterObject,

PVOID PacketBuff, ULONG Size, BOOLEAN Sync)

{

//等待时间间隔的逝去

    while( CurTicks.QuadPart <= TargetTicks.QuadPart )

       QueryPerformanceCounter(&CurTicks);

}

 

INT NPF_BufferedWrite(

    IN PIRP Irp,

    IN PCHAR UserBuff,

    IN ULONG UserBuffSize,

    BOOLEAN Sync)

{

//等待直到时间间隔逝去

    while( CurTicks.QuadPart <= TargetTicks.QuadPart )

       CurTicks = KeQueryPerformanceCounter(NULL);

    …

}  

对于发送队列发送方式的时间间隔的图示如下图:

9-7 等待时间间隔示意图

NPF_BufferedWrite函数中处理每个包之间的时间间隔,而在PacketSendPackets函数中处理每块数据包之间的时间间隔,这与第一个问题相关。这也就是在PacketSendPacketsNPF_BufferedWrite两个函数中都能看见类似的忙等待代码的原因之所在。