-------------------------继续----------------------------
if
( Sync ){/*
处理与时间戳的同步发送
*/
//
如果需要阻塞超过约
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
函数
需要返回的字节大小需要进行头部对齐。
Ø
延迟时间的处理。
在PacketSendPackets与
NPF_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
函数中处理每块数据包之间的时间间隔,这与第一个问题相关。这也就是在PacketSendPackets与
NPF_BufferedWrite
两个函数中都能看见类似的忙等待代码的原因之所在。