也谈IO完成端口

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了也谈IO完成端口相关的知识,希望对你有一定的参考价值。

不久前排查的一个Bug最后是利用IO完成端口解决的,本人对这块的东西并没有熟练掌握,有必要深入了解下,本文会持续更新...

一. 异步设备IO概述

众所周知,合理使用线程能显著提高程序的运行效率,如果在多处理器的机器上为每个线程指定一个处理器,则可以同时执行多个操作,吞吐量能够大大提高。看着相当理想,一旦线程中有IO操作,情况就变得不一样了。相对于CPU的运算速度,IO操作(比如从文件或者网络中读取数据或者向文件或者网络中写入数据)的速度是相当慢的,因此如果线程以同步的方式(阻塞)进行IO操作,在操作没有完成之前,它就挂在那儿闲着了,干不了别的,对性能有一定的影响。为了不让线程闲下来,则必须采用异步(非阻塞)的方式,下面看下异步操作的一般流程。

异步操作的流程:  线程向设备发出一个异步IO请求,IO请求被传给设备驱动程序(加入设备驱动程序的队列中),紧接着设备驱动程序会完成实际的IO操作,此时线程并没有挂起继续干它的活儿,等到设备驱动程序完成了IO请求的处理时,它会将相应的状态告知应用程序(数据已发送,数据已收到,或发生了错误)。

技术分享

可发现,异步IO操作实际上包括两大步骤:

第一,把异步IO请求加入设备驱动程序队列。首先,在 CreateFile 的 dwFlagsAndAttributes 参数中指定 FILE_FLAG_OVERLAPPED 标志来打开设备;然后,使用 ReadFileWriteFile 函数将IO请求加入设备驱动程序的队列中。

第二,接收设备驱动程序IO请求完成的通知。Windows提供了4种不同的方法来接收IO请求已经完成的通知。如下表所示,本文将重点分析IO完成端口技术,后面会写篇文章分析其它三种技术。

用来接收I/O完成通知的方法
技术 摘要
触发设备内核对象

1. 当向一个设备发出多个IO请求的时候,该方法没用;

2. 允许一个线程发出请求,另一个线程对结果进行处理

触发事件内核对象

1. 允许向一个设备同时发出多个IO请求;

2. 允许一个线程发出请求,另一个线程对结果进行处理

使用可提醒IO

1. 允许向一个设备同时发出多个IO请求;

2. 发出IO请求的线程必须对结果进行处理

使用IO完成端口

1. 允许向一个设备同时发出多个IO请求;

2. 允许一个线程发出请求,另一个线程对结果进行处理

 

二. IO端口相关的API

 

三. 例子

以上是关于也谈IO完成端口的主要内容,如果未能解决你的问题,请参考以下文章

菜鸟 关于WSASend 函数,IO完成端口模型

使用套接字时,哪些 IO 操作会导致完成数据包发送到完成端口?

IO 完成端口初始读取和双向数据

IO 完成端口:WSARecv() 是如何工作的?

使用 io 完成端口时,WriteFile 是不是会在完成时立即发布完成数据包

完成端口