windows IOCP 实践
2020-12-13 05:17
标签:http 使用 数据 io for re 有人说 windows IOCP 是 windows 上最好的东西。 IOCP 是真正的异步 IO,意味着每次发起一个 IO 请求,该调用本身则立即返回, 而包括 IO 操作和数据从内核缓冲区到用户缓冲区之间的拷贝都由系统完成,直到这个过程结束系统才通知用户进程。 linux 上没有这样的异步 IO。 代码在此,服务端程序比较简单,可以自己实现并验证。 windows IOCP 实践,搜素材,soscw.com windows IOCP 实践 标签:http 使用 数据 io for re 原文地址:http://www.cnblogs.com/persistentsnail/p/3862433.html关于 windows IOCP
IOCP 的使用
CreateIoCompletionPort
这个 API 用于创建 IOCP, 最后一个参数则是指定线程池中线程个数,一般来说取 CPU * 2 ,这样可以最充分使用多核 CPU ,又降低了线程间的切换。CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, dwNumberOfConcurrentThreads)
CreateIoCompletionPort
(API 设计有些太随意了吧,难道有什么历史原因?)。HANDLE h = CreateIoCompletionPort(hDevice, hCompletionPort, dwCompletionKey, 0);
GetQueuedCompletionStatus
调用上。GetQueuedCompletionStatus
返回时从 IO 完成队列中取出一个 completion packet。线程池线程阻塞时是由系统负责完成调度的。IOCP 内部的一些数据结构
GetQueuedCompletionStatus
就是在这个队列上等待。GetQueuedCompletionStatus
时,就会被放进一个等待队列,IO 完成端口内核对象根据此队列知道有哪些线程在等待处理completion packet。线程等待队列是按照 LIFO 的方式入队的,也就是当有一个 completion packet 到来时,系统先唤醒最后调用GetQueuedCompletionStatus
进入等待队列的线程。IOCP 和线程池的相互作用
GetQueuedCompletionStatus
来与一个 IO 完成端口关联起来,但是一个线程只能关联一个 IOCP,当线程退出或者指定了其他的 IOCP或者关闭了 IOCP,线程才与这个 IOCP 解开绑定。GetQueuedCompletionStatus
时就会立即返回,该线程处理完这个 completion packet 再次调用GetQueuedCompletionStatus
又会立即返回。在处理 completion packet过程中,虽然完成队列中始终有 completion packet 待处理,但是因为并发值为 1 的原因,系统不会去调度其他线程来执行,尽管关联 IOCP 的线程不止一个。同时也避免了线程切换的开销,因为始终都是这一个线程在执行。Sleep
, WaitFor*
,或者一个同步 IO 函数,或者任何可以引起当前线程从运行状态变为等待状态的函数时,IOCP 就会立即调度其他关联的线程,维持始终有一个线程在运行。IOCP 使用过程中遇到的问题
GetQueuedCompletionStatus
等待 IOCP 完成队列处。几乎所有的异步 IO 函数都是如此。但是所幸似乎即使立即返回 0 ,完成队列中也会有一个 completion packet,所以只在工作线程中的完成队列中等待 IO 完成也不会出错。一个收发 TCP 应用协议包的程序示例