Windows IOCP 文档建议每个完成端口的每个可用核心不超过一个线程。超线程使内核数量翻倍。由于使用 IOCP 会导致所有实际用途的事件驱动应用程序,因此使用线程池会为调度程序添加不必要的处理。
如果您考虑一下,您就会明白原因:应该尽快为事件提供完整的服务(或在初始处理后将其放入某个队列中)。假设 5 个事件排队到 4 核计算机上的 IOCP。如果有 8 个线程与 IOCP 相关联,则调度程序可能会中断一个事件以使用另一个低效的线程开始为另一个事件提供服务。如果被中断的线程位于临界区中,也可能很危险。使用四个线程,您可以同时处理四个事件,一旦一个事件完成,您就可以从 IOCP 队列中的最后一个剩余事件开始。
当然,您可能有用于非 IOCP 相关处理的线程池。
编辑__ _ __ _ __ _ __ _ __ _ _
套接字(文件句柄也可以正常工作)与 IOCP 相关联。完成例程在 IOCP 上等待。一旦请求的对套接字的读取或写入完成操作系统 - 通过 IOCP - 释放等待 IOCP 的完成例程并返回您在调用读取或写入时提供的附加信息(我通常将指针传递给一个控制块)。因此,完成例程立即“知道”在哪里找到与完成相关的信息。
如果您传递了引用控制块(类似)的信息,则该控制块(可能)需要跟踪已完成的操作,以便知道下一步该做什么。IOCP 本身既不知道也不关心。
如果您正在编写连接到 Internet 的服务器,则服务器将发出读取以等待客户端输入。该输入可能在一毫秒或一周后到达,当它到达时,IOCP 将释放分析输入的完成例程。通常,它会以包含输入中请求的数据的写入响应,然后在 IOCP 上等待。当写入完成时,IOCP 再次释放完成例程,该例程看到写入已完成,(通常)发出新的读取并开始新的循环。
因此,基于 IOCP 的应用程序通常消耗很少(或不消耗)CPU,直到完成发生,此时完成例程完全倾斜,直到完成处理,发送新的 I/O 请求并再次等待完成端口. 除了 IOCP 超时(可用于指示内务处理等)之外,所有与 I/O 相关的东西都发生在操作系统中。
为了使事情进一步复杂化(或简化),不必使用 WSA 例程来服务套接字,Win32 函数 ReadFile 和 WriteFile 工作得很好。