MSDN documentation中查找CreateIoCompletionPort,我们读到:



但是,我发现的文档没有表明IoCompletionPort实际上创建了任何线程。

实际上,Microsoft提供的example使用以下代码来确定有多少个处理核心可用(而不是将0传递给NumberOfConcurrentThreads),然后实际上创建了那么多线程。

// The general value of the thread count is the system's processor count.
SYSTEM_INFO sysInfo = { 0 };
GetNativeSystemInfo(&sysInfo);
const DWORD dwThreadCount = sysInfo.dwNumberOfProcessors;

// A class in the example that wraps around IoCompletionPort
IOCompletionPort port;

// Construct the thread pool
HANDLE* hThreads = new HANDLE[dwThreadCount];
for (DWORD i = 0; i < dwThreadCount; ++i) {
    // The threads run CompletionThread
    hThreads[i] = CreateThread(0, 0, IOCompletionThread, &port, 0, NULL);
}

在我看来,这表明某种程度上存在与IoCompletionPort相关的“承载能力”。但是,这表现如何?我很难理解如何(或什至为何如此)可访问完成端口的线程如何防止从完成端口出队。

实际上,我尝试将创建线程的行修改为new HANDLE[++dwThreadCount](并从声明中删除了const说明符),并且该示例似乎可以毫无提示地执行。我只是在执行结束时注意到一个额外的超时错误。

我目前唯一的结论就是说NumberOfConcurrentThreads是一个“虚拟”变量,没有实际用途,那么我会缺少什么呢?

最佳答案

IOCP基于 KQUEUE object:

struct KQUEUE {
    DISPATCHER_HEADER Header;
    LIST_ENTRY EntryListHead;
    ULONG CurrentCount;
    ULONG MaximumCount;
    LIST_ENTRY ThreadListHead;
};

如果由MaximumCount(计数== 0)初始化,则由KeNumberProcessors分配KeInitializeQueue;如果是从CreateIoCompletionPort(ZwCreateIoCompletion)初始化,则由NumberOfConcurrentThreads分配。
CurrentCount是绑定(bind)到此KQUEUE的“ Activity ”(未等待)线程的数量(在ETHREAD结构中有一个特殊字段:KQUEUE* Queue)。

如果线程试图通过调用KQUEUEKeRemoveQueue(ZwRemoveIoCompletion)从GetQueuedCompletionStatus中删除数据包,而IOCP中没有数据包(EntryListHead为空),那么该线程当然会进入等待状态。

但是,如果存在数据包,系统将查看CurrentCountMaximumCount。如果是CurrentCount < MaximumCount,则将删除一个数据包(并且CurrentCount++递增)。否则,线程将进入等待状态。

如果一个线程向其他线程先前正在等待的IOCP插入一个新数据包,则只有在(CurrentCount < MaximumCount)时,才会以LIFO顺序唤醒一个数据包。

什么时候:
  • 线程开始在某个对象上等待(通过KeWaitForObject)
  • 线程被挂起(这也是内部对KeWaitForObject的调用)
  • KeDelayExecution(Sleep)称为

  • 系统查看Thread->Queue,如果不是0,则CurrentCount--会递减。此外,如果IOCP中存在数据包,线程正在等待它,并且CurrentCount < MaximumCount则一个线程将被唤醒。

    因此,逻辑实际上非常复杂,但是重点仅在于MaximumCount线程将能够立即处理来自IOCP的数据包。

    通常,最好的值是KeNumberProcessors,但是(在某些特殊情况下)分析工具可以帮助您确定一个更适合您情况的其他值。

    关于c++ - 如何在 `NumberOfConcurrentThreads`中使用参数 `CreateIoCompletionPort`,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38133870/

    10-15 05:26