IOCP

维基百科,自由的百科全书
跳转至: 导航搜索

输入输出完成端口(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操作系统[编辑]

使用CreateIoCompletionPort函数创建IOCP,还可以把socket或文件句柄与IOCP关联起来。

请求I/O的线程,使用GetQueuedCompletionStatus函数等待放入IOCP的I/O完成包(completion packet)。IOCP可以使用一个线程池。每个线程同时至多关联一个IOCP。阻塞在IOCP上的线程按照后进先出(LIFO)顺序被释放;而一个线程的完成包按照先进先出(FIFO)顺序从IOCP的队列中取走。

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

IOCP不能跨进程使用。

内部结构[编辑]

Windows中利用CreateIoCompletionPort命令创建完成端口对象时, 操作系统内部为该对象自动创建了5个数据结构,分别是[3]

  • 设备列表(Device List): 每当调用CreateIoCompletionPort函数时,操作系统会将该设备句柄添加到设备列表中;每当调用CloseHandle关闭了某个设备句柄时,系统会将该设句柄从设备列表中删除
  • IO完成请求队列(I/O Completion Queue-FIFO):当I/O请求操作完成时,或者调用了PostQueuedCompeltionStatus函数时,操作系统会将I/O请求完成包添加到I/O完成队列中。当操作系统从完成端口对象的等待线程队列中取出一个工作线程时,操作系统会同时从I/O完成队列中取出一个元素(I/O请求完成包。
  • 等待线程队列(WaitingThread List-LIFO):当线程中调用GetQueuedCompletionStatus函数时,操作系统会将该线程压入到等待线程队列中。为了减少线程切换,该队列是LIFO。当I/O完成队列非空,且工作线程并未超出总的并发数时,系统从等待线程队列中取出线程,该线程从自身代码的GetQueuedCompletoinStatus函数调用处返回并继续运行。
  • 释放线程队列(Released Thread List):当操作系统从等待线程队列中激活了一个工作线程时,或者挂起的线程重新被激活时,该线程被压入释放线程队列中,也即这个队列的线程处于运行状态。这个队列中的线程有两个出队列的机会:一是当线程重新调用GetQueuedCompeltionStatus函数时,线程被添加到等待线程队列中;二是当线程调用其他函数使得线程挂起时,该线程被添加到挂起线程队列中。
  • 暂停线程队列(Paused Thread List):释放线程队列中的线程被挂起的时候,线程被压入到挂起线程队列中;当挂起的线程重新被唤醒时,从挂起线程队列中取出放入到释放线程队列。

參考資料[编辑]

外部連結[编辑]