此條目需要擴充。 (2014年4月11日)请協助改善这篇條目,更進一步的信息可能會在討論頁扩充请求中找到。请在擴充條目後將此模板移除。
此條目需要精通或熟悉相关主题的编者参与及协助编辑。 (2014年4月11日)請邀請適合的人士改善本条目。更多的細節與詳情請參见討論頁

输入输出完成端口(Input/Output Completion Port,IOCP), 是支持多个同时发生的异步I/O操作的应用程序编程接口,在Windows NT的3.5版本以後[1],或AIX 5版以後[2]Solaris第十版以後,開始支持。

IOCP特别适合C/S模式网络服务器端模型。因为,让每一个socket有一个线程负责同步(阻塞)数据处理,one-thread-per-client的缺点是:一是如果连入的客户多了,就需要同样多的线程;二是不同的socket的数据处理都要线程切换的代价。

原理

通常的办法是,线程池中的工作线程的数量与CPU内核数量相同,以此来最小化线程切换代价。一个IOCP对象,在操作系统中可关联着多个Socket和(或)文件控制端。 IOCP对象内部有一个先进先出(FIFO)队列,用于存放IOCP所关联的输入输出端的服务请求完成消息。请求输入输出服务的进程不接收IO服务完成通知,而是检查IOCP的消息队列以确定IO请求的状态。 (线程池中的)多个线程负责从IOCP消息队列中取走完成通知并执行数据处理;如果队列中没有消息,那么线程阻塞挂起在该队列。这些线程从而实现了负载均衡。

Windows操作系统

IOCP是唯一一个不需要安全属性的Windows内核对象。 这是因为IO完成端口在设计时就是只在一个进程中使用。

使用CreateIoCompletionPort函数创建一个新的IOCP,或把socket或文件句柄与一个已存在的IOCP关联起来。

一个线程,第一次调用GetQueuedCompletionStatus函数时,该线程就成为关联了该IOCP的线程,直到下述三种情形之一发生:

即,一个线程在任何时刻最多关联一个IOCP。

线程调用GetQueuedCompletionStatus函数等待放入IOCP的I/O完成包(completion packet)。IOCP拥有一个线程池。阻塞在IOCP上的线程按照后进先出(LIFO)顺序被释放(这是为了减少线程切换的代价);而一个线程的完成包按照先进先出(FIFO)顺序从IOCP的队列中取走。IOCP有一个最大允许并发的线程数量上限,在CreateIoCompletionPort函数中指定,每次I/O完成包在从队列取走前检查关联于该IOCP且正在并发执行的线程数量是否达到该限。因其他原因(如调用SuspendThread函数)而挂起的线程不算作正在执行的线程。CompletionKey(完成键)一般作为“单句柄数据”的结构体(PER_HANDLE_DATA),用来标识是哪个设备的I/O完成操作已经完成。IO重叠结构(Overlapped)一般作为“单IO数据”的结构体(PER_IO_DATA),该结构体的第1个成员为OVERLAPPED结构体,用来标识是设备的具体哪个操作。

线程可以用PostQueuedCompletionStatus函数在IOCP上投寄一个完成包。

关闭IOCP之前,必须先关闭关联在该IOCP之上的所有File Handle或socket。

内部结构

Jeffrey Richter英语Jeffrey Richter说:“完成端口可能是最为复杂的内核对象”。[3] Windows中利用CreateIoCompletionPort命令创建完成端口对象时, 操作系统内部为该对象自动创建了5个数据结构,分别是:

參考資料

  1. ^ Windows I/O Completion Ports. [2014-04-11]. (原始内容存档于2014-03-20). 
  2. ^ Configuring IOCP on AIX 5 and 6. [2014-04-11]. (原始内容存档于2013-06-30). 
  3. ^ 《Windows via C/C++》 Fifth Edition (December 2007) (Jeffrey Richter and Christophe Nasarre) Page292.

外部連結