为什么叫做重叠端口?

其实这个标题有点“标题党”的味道,为了大家搜索方便我故意冠以IOCP编程之名,其实重叠IO编程并不一定需要IOCP,而IOCP编程就一定需要重叠IO。是不是已经被这句话给绕晕了?总之是为了更好的应用IOCP,所以要理解重叠IO。这篇文章的核心就是讨论重叠IO的来龙去脉。

在很久很久以前,在用C语言写DOS程序的年代,就有了很完整的IO标准库支撑,printf输出字符到屏幕,fopen,fwrite,fread等操作文件,甚至还有一些函数可以在屏幕上绘图,到了Windows时代,有了API,当然输出到屏幕的函数被GUI GDI的API代替,而文件的操作就被CreateFile、WriteFile、ReadFile等代替,在使用这些函数时,其实很多时候我们会感觉到“慢”,为什么呢?因为它们的工作方式就是等待输入或输出操作结束后才返回,而这些IO设备通常都是些慢的要死的设备,等它们完成工作再返回,通常CPU都打瞌睡了。

当然有些程序可以没有明显的屏幕输入输出操作,可是不同硬盘打交道的软件就很少了。假如访问硬盘比较频繁时,可以明显感觉到程序的性能下降。比如,为一个程序挂接了一个朝磁盘文件写入日志的功能,结果往往会发现,当打开日志时,程序就会慢的像蜗牛一样,而关闭日志系统一切又正常了,这时磁盘日志功能因为速度问题而变成了鸡肋。

上面说的工作方式,其实是一种被Windows系统称之为“同步”的方式,也就是说你的程序工作的步骤和那些慢速的IO设备是一致的,IO设备要多长时间完成操作,你的程序就要多长时间完成操作。这听起来有点恐怖,但似乎好像这又是合理的。其实这并不合理,比如还是那个磁盘日志系统,往往在写入日志记录的时候,根本不用等待这个写入的完成,程序逻辑可以自由的继续往下执行。其实大多数情形下,都会自然的希望程序这样去执行IO操作。

当然Windows平台也考虑到了这种情况,所以就提供了一种称之为“重叠IO”的操作方式来“异步”操作IO,目前支持重叠IO操作的系统对象除了文件,还有管道、串口、甚至SOCKET都可以用这种方式来操作。

具体的在Windows平台上,异步IO的原理其实比较简单,就是你调用完IO函数后,函数会立即返回,你的程序或者说当前线程会继续往下执行,而你需要建立一个“可警告(alert able)”的线程来等待接收IO操作完成的通知。这样调用IO函数与IO函数的完成返回就成了“异步”方式执行。对于调用者来说,它的目标就集中到了整个程序逻辑的合理性问题上,而不用去关心IO操作的结果。

当然也有些情况下,还是需要知道IO操作完成的结果,比如读取图片文件,然后显示,乍一想貌似这种情况使用“异步”方式是不很合理的,其实这时也完全可以用异步方式来操作,并提高一定的性能。假设需要显示的不止一张图片,那么就可以将所有的读取操作一次性调用完成,可能是几十个,也可能是几百个,然后在IO操作完成的回调函数中按照图片位置,做相应的显示即可。

虽然可以很容易的理解重叠IO的异步工作特性,但是对于这个奇怪的名字估计很多人还是比较迷惑的,为什么叫重叠呢?为什么不直接叫异步IO呢?其实这个名字正好显示了这种IO操作方式的精髓“重叠”。

其实能够理解重叠IO的异步特性或者原理,只是理解了它的一部分,或者说只是个表象。要理解重叠,就首先让我们回到那个磁盘日志系统上来,假设这是一个写入比较频繁的日志系统(其实很多日志系统都是如此),如前所述如果用“同步”的方式来写入,那么性能就会很低下,而如果要用“异步”方式操作,那么是不是需要等待一个完成通知之后,再进行下一个写入呢(这是很多初学者容易迷惑的地方)?其实不是,这里就是重叠的意思了,也就是说,你不必等到某个IO操作完成,就可以调用下一个IO操作,而这些IO操作可以被看做是堆叠在一起,等待完成,这就是重叠IO的真谛。这些“重叠”在一起的IO操作,将按照一定的顺序被完成,但是它们的完成通知并不是严格按照顺序回调,尤其是在多线程环境中,回调基本是随机的。调用顺序,和完成回调顺序是完全不同的两个概念,这一点一定要区别清楚。

理解了原理,就让我们具体来看看重叠IO如何编程。关于IOCP调用重叠IO的例子,可以参看本人博客中其他几篇关于IOCP的文章。

要想重叠IO就首先要有一个重叠结构,这个结构被命名做OVERLAPPED,如果你看到某个API函数参数中有这个字眼,你基本就可以确定这个函数是可以“重叠”操作的。当然要让某个系统对象打开重叠IO的特性,就需要在创建该对象时明确指定一些标志。 比如调用CreateFile、CreateNamePipe、WSASocket等。

重叠IO的完成通知有两种方式可以得到,一种是通过传递一个Event内核对象的句柄,另一种就是传递一个回调函数的指针。

posted @ 2018-03-20 14:13  老耗子  阅读(114)  评论(0编辑  收藏  举报