1.5.2.1.5 PacketSetBuff函数
函数PacketSetBuff设置一个与捕获关联的内核缓冲区的大小。函数原型如下:
BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
;
参数AdapterObject指向一个_ADAPTER结构体,参数dim是缓冲区新的大小,采用千字节为单位。
函数如果成功,返回TRUE,如果没有足够的内存分配,则函数失败,返回FALSE。
函数的主要代码如下:
BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
{
…
if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
{
Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
BIOCSETBUFFERSIZE,&dim,sizeof(dim),
NULL,0,&BytesReturned,NULL);
}
else
{//
一个未知类型的适配器请求设置缓冲区的大小
Result = FALSE;
}
return Result;
函数最后由NPF驱动程序的NPF_IoControl函数的case BIOCSETBUFFERSIZE: 分支语句在底层实现。
当一个新的大小被设置后,旧缓冲区内的数据被丢掉,同时存储在内的数据包被丢弃。
注意:内核缓冲区的大小严重影响捕获过程的性能。当应用程序忙时,驱动程序中一个足够大的缓冲区能够保存数据包,可弥补应用程序的延时,避免在网路高峰期时丢失数据包。当一个驱动程序的实例被打开时,缓冲区大小设置为0,因此程序员应该记得设置它为一个合适的值。比如wpcap在开始捕获时设置该缓冲区的大小为1MB。
1.5.2.1.6 PacketInitPacket与函数
函数PacketInitPacket主要初始化一个_PACKET结构体。函数原型如下:
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
参数lpPacket指向需要初始化的结构体,参数Buffer是一个指向用户所分配的缓冲区,其将用来缓冲捕获的数据包。参数Length为该缓冲区的大小。这也是从驱动程序到应用程序一次读操作所能传递最大的数据大小。
函数的实现如下:
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
{
lpPacket->Buffer = Buffer;
lpPacket->Length = Length;
lpPacket->ulBytesReceived = 0;
lpPacket->bIoComplete = FALSE;
注意:与该PACKET结构体相关联的缓冲区的大小,是一个能够明显影响捕获过程性能的参数,既然该缓冲区用来存储从驱动程序所接收的数据包。驱动程序能够只用一次系统调用(参见PacketReceivePacket函数)返回几个数据包。与PACKET结构体相关联的,传递给PacketReceivePacket函数的缓冲区的大小,限制了一次调用中传递给应用程序的数据包的数目。因此使用PacketInitPacket函数设置一个大的缓冲区,可以显著降低系统调用的次数,减少捕获过程给处理器带来的压力。