IOCP原理
2017-12-06 16:54
381 查看
简介
I/O完成端口是为多处理器系统处理多重异步I/O请求线程模型。I/O完成端口就是与线程池配合使用的。
API
CreateIoCompletetionPort 创建IOCP和关联一个或多个句柄到端口上。GetQueuedCompletionStatus 等待或从IOCP队列中取出完成包(completion packet)。
PostQueuedCompletionStatus 把一个完成包压入IOCP的队列。
CloseHandle 关闭IOCP
注意
微软建议并发线程数指定为CPU核心数。IOCP自动关联到创建它的进程且不能共享给其他进程。
一个线程只能关联一个IOCP。
IOCP不能严格保证事件的出列顺序。
微软建议应该先把IOCP所关联的资源(包括所关联的句柄)先释放,最后再释放IOCP。
原理
调用GetQueuedComoletionStatus(第一次调用)的用户线程会被添加到等待线程队列。等待线程队列的LIFO机制使得性能更优。
发生以下三种情况时,线程会与IOCP取消关联:
- 线程退出。
- 线程关联新的IOCP
- IOCP关闭
I/O完成端口相关内核结构:
1. 设备列表 2. I/O完成队列(先入先出,FIFO) 3. 等待线程队列(后入先出,LIFO) 4. 已释放线程列表(可以理解为工作线程列表) 5. 已暂停线程列表
设备列表
内容:• hDevice
• dwCompletionKey下·
添加:
• CreateIoCompletionPort被调用
删除:
• 设备句柄关闭
I/O完成队列(先入先出)
内容:• dwBytesTransferred
• dwCompletionKey
• pOverlapped
• dwError
添加:
• I/O请求完成
• PostQueuedCompletionStatus
删除:
• 完成端口从等待线程队列中删除一项(GetQueuedCompletionStatus成功返回)
等待线程队列(后入先出)
内容:• dwThreadId
添加:
• 线程调用GetQueuedCompletionStatus进入休眠状态。
删除:
• I/O完成队列不为空 && 已释放线程列表项数(即正在运行的工作线程数)小于最大并发线程数。(GetQueuedCompletionStatus会先从I/O完成队列中删除对应的项,接着将 dwThreadId转移到已释放线程列表,最后函数返回)。
已释放线程列表(可以理解为工作线程列表)
内容:• dwThreadId
添加:
• 完成端口在等待线程队列中唤醒一个线程
• 已暂停的线程被唤醒
删除:
• 线程再次调用GetQueuedCompletionStatus(dwThreadId再次回到等待线程队列)
• 线程调用一个函数将自己挂起(dwThreadId转移到已暂停线程列表)
已暂停线程列表
内容:• dwThreadId
添加:
• 已释放的线程调用一个函数将自己挂起
删除:
• 已挂起的线程被唤醒(dwThread回到已释放线程队列)