但是,如果完成例程足以实现我的目标:告诉套接字发送这块数据并在完成时通知我,那么我为什么应该使用IOCP呢?
我理解,在与
CreateThreadpoolIo
等组合使用时,IOCP会使用操作系统线程池。然而,“普通”的重叠I/O也必须使用单独的线程吗?那么区别/劣势是什么?我的回调由I/O线程调用并阻塞其他东西吗?提前感谢, Christoph
CreateThreadpoolIo
等组合使用时,IOCP会使用操作系统线程池。然而,“普通”的重叠I/O也必须使用单独的线程吗?那么区别/劣势是什么?我的回调由I/O线程调用并阻塞其他东西吗?Windows IOCP文档建议每个完成端口的可用核心最多使用一个线程。超线程会使核心数量翻倍。由于使用IOCP导致几乎可以被视为事件驱动的应用程序,使用线程池会给调度器增加不必要的处理。
如果你仔细想一想,就能理解为什么了:一个事件应该尽快完整地服务(或在初始处理后放入某个队列中)。假设有五个事件排队到一个4核电脑上的IOCP。如果与IOCP关联的线程有八个,你就有可能让调度器中断一个事件来开始服务另一个事件,使用另一个线程来处理,这是低效的。而且,如果被中断的线程在临界区内,这样做还可能是危险的。有四个线程时,你可以同时处理四个事件,并在完成一个事件后立即开始处理IOCP队列中剩下的最后一个事件。
当然,你可能会为非IOCP相关的处理设置线程池。
编辑________________
套接字(文件句柄也可以)与IOCP相关联。完成例程在IOCP上等待。一旦从套接字请求的读取或写入完成,操作系统通过IOCP释放等待在IOCP上的完成例程,并返回您调用读取或写入时提供的附加信息(我通常传递指向控制块的指针)。因此,完成例程立即“知道”在哪里找到与完成相关的信息。
如果您传递了引用控制块(类似的)的信息,则该控制块(可能)需要跟踪已完成的操作,以便知道下一步该做什么。IOCP本身既不知道也不关心。
如果您正在编写连接到互联网的服务器,则服务器将发出读取以等待客户端输入。该输入可能会在一毫秒或一周后到达,当它到达时,IOCP将释放完成例程并分析输入。通常,它会响应包含输入中请求的数据的写入,然后等待IOCP。当写入完成时,IOCP再次释放完成例程,该例程看到写入已完成,(通常)发出新的读取并开始新的循环。
因此,基于IOCP的应用程序通常在完成发生之前几乎不会消耗任何CPU资源(或者根本不会),在完成例程开始全力处理直到完成处理、发送新的I/O请求并再次等待完成端口的过程中才会消耗大量CPU资源。除了IOCP超时(可用于信号处理或其他操作)外,所有与I/O相关的操作都在操作系统中进行。
为了进一步复杂化(或简化)事情,使用WSA例程服务套接字并非必要,Win32函数ReadFile和WriteFile同样可以正常工作。
ExistingCompletionPort
参数关联到端口的句柄数量? - Christoph