我正在编写一个 Windows 过滤平台内核模式驱动程序,该驱动程序的目标是捕获特定层上的所有流量,并将这些流量传回用户模式,以便进一步分析。驱动程序永远不需要阻塞任何交通,classifyOut 始终设置为FWP_ACTION_CONTINUE
。
下面的代码在我的 Classify 函数中用于对收到的数据包进行排队。
classifyOut->actionType = FWP_ACTION_CONTINUE;
do
{
if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
{
break;
}
if (layerData != NULL)
{
PNET_BUFFER_LIST netBufferList = (PNET_BUFFER_LIST) layerData;
PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(netBufferList);
if (packetQueueSize >= 2048)
{
ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
packetQueueSize--;
}
ULONG netBufferSize = NET_BUFFER_DATA_LENGTH(netBuffer);
PACKET_ITEM* allocatedPacket = InitalizePacketItem(
netBuffer,
netBufferSize
);
if (allocatedPacket == NULL)
{
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
break;
}
ExInterlockedInsertTailList(
&packetQueue,
&allocatedPacket->listEntry,
&packetQueueLock
);
allocatedPacket = NULL;
packetQueueSize++;
}
} while (FALSE);
该PACKET_ITEM
结构定义如下
typedef 结构 _PACKET_ITEM { LIST_ENTRY 列表条目; PVOID 数据; 超长数据; } PACKET_ITEM;
我正在使用反向调用模型将此数据包数据从内核模式传递到用户模式。一旦检测到已发送正确的 IOCTL,内核驱动程序将使用以下代码。
status = WdfRequestRetrieveOutputBuffer(request, 0, &buffer, &bufferSize);
if (!NT_SUCCESS(status))
{
break;
}
PLIST_ENTRY listEntry = ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
if (listEntry == NULL)
{
break;
}
PACKET_ITEM* packetItem = CONTAINING_RECORD(
listEntry,
struct _PACKET_ITEM,
listEntry
);
RtlCopyMemory(
buffer,
packetItem->data,
packetItem->dataLen);
status = STATUS_SUCCESS;
WdfRequestCompleteWithInformation(
request,
status,
packetItem->dataLen
);
FreePacketItem(packetItem);
这段代码似乎会在短时间内大大降低网络速度,例如,在尝试在 Web 浏览器中加载网站时会导致超时。
我认为这是由自旋锁和该驱动程序捕获的通过网络传输的大量数据包引起的。
我的问题如下
- 自旋锁很可能在这里引起我的问题吗?如果是这样
classifyOut->actionType
在分配任何内存以将数据复制到我的队列中之前,是否可以立即设置并返回此值。我认为这会阻止减速的发生?- 我还应该做些什么来防止这种情况发生?
- 如果不,
- 是什么导致这里变慢的问题?