数年前做一个项目时,参考了《Programming Server-Side Application For Microsoft Windows 2000》一书,该书作者就是大名鼎鼎的Jeffery Rechard,《Windows核心编程》的作者。当时为工作组内其他人翻译了第二章。时至今日,将这个老文发出来为我的博客充数,也希望对别人有所帮助。
第二章 设备
I/O
与线程间通信
我无法完全表达本章的重要性,本章覆盖了关于实现高性能,可伸缩应用程序的两个本质性主题:设备I/O和线程间通信。一个可伸缩的应用程序在处理大量并发事务时,应像处理小量并发事务时一样高效。对于服务应用,典型的操作是处理不定期的客户端请求,并且该请求所需要的处理能力不能预见。这些请求经常来自于I/O设备,例如网络适配器;通常请求处理接着会做一些附加的I/O操作,比如磁盘文件访问等等。
对于微软的Windows应用程序,线程是分拆工作的最好机制。每一个线程被分配给一个处理器,这样具有多处理器的机器就能够同时执行多个操作,以提高吞吐量。当某个线程提交一个设备I/O请求时,该线程将被暂时性挂起直到设备完成了I/O请求。这种挂起严重降低了性能,因为此时线程不能做其他有用的工作,如初始化另一个客户端请求并进行处理。因此,简单的说,你应该保持线程始终在忙的状态,做有用的工作,而不是简单的挂起。
要保持线程忙碌,需要进行线程间通信以使线程间彼此了解将要进行的操作。微软已经花费了数年时间在这一领域进行研究和测试,而且发展出很好的机制来进行线程间通信。这种机制称为I/O完成端口(I/O completion port),它能够帮你创建高性能的,可伸缩的应用。一个例子是Windows 2000中新的任务内核对象(Job kernel object):当一个任务对象监视到有操作需要进行处理,它会发送一个通知事件给一个I/O完成端口。
JobLab应用程序的示例,可以从《Programming Application For microsoft Windows, Forth Edition》(Windows核心编程)得到,该例子描述了如何使I/O完成端口和任务对象一起工作。
根据多年的Windows开发经验,我发现越来越多的人在使用I/O完成端口,我感觉每一个Windows开发人员必须透彻理解I/O完成端口是如何工作的。本书中许多示例程序都使用了I/O完成端口。即使我在本章关于设备I/O的主题中阐述I/O完成端口,需要注意的是:I/O完成端口并非是完全针对设备I/O的,简单的说,它是一个公认的用于应付无限的请求处理的进程间通信机制。