由于Spinlock导致Windows过滤平台网络速度下降

时间:2018-04-11 14:21:34

标签: multithreading winapi spinlock windows-kernel wfp

我正在编写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 struct _PACKET_ITEM {
    LIST_ENTRY listEntry;
    PVOID data;
    ULONG dataLen;
} 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);

此代码似乎会在一段时间后大幅减慢网络速度,例如在尝试在网络浏览器中加载网站时会导致超时。

我认为这是由自旋锁和通过网络传输的大量数据包引起的,这些数据包是由此驱动程序捕获的。

我的问题如下

  • 螺旋锁是否肯定会引起我的问​​题?如果是这样
    • 是否可以立即设置classifyOut->actionType并在分配任何内存之前返回此值以将数据复制到我的队列中。我认为这可以防止发生减速?
    • 我还应该做些什么来阻止这种情况?
  • 如果没有,
    • 这里减缓导致问题的原因是什么?

0 个答案:

没有答案