深度探索IO完成端口.docVIP

  1. 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
深度探索IO完成端口

引言 要想编写一个高性能的服务器应用程序,必须实现一个高效的线程模型。让太少或者太多的服务器线程来处理客户的请求,都可能导致性能问题。例如,如果一个服务器创建单个线程来处理所有的请求,那么客户端可能长期等待而得不到响应,因为服务器同一时刻只能忙于处理一个请求。当然单个线程也能并发处理多个请求,当I/O操作被启动时,它可以从一个请求切换到另一个请求,但是这种结构相当复杂,并且不能充分利用多处理器的优势。在另一个极端,服务器可以创建一个大规模的线程池,这样几乎每一个客户请求都可以由一个专门的线程来处理。这种情形通常会导致线程频繁切换:大量线程被唤醒,执行CPU处理,阻塞等待I/O,然后在请求完成之后又一次阻塞以等待新的请求。如果没有别的情况,太多的线程将导致过多的上下文切换,因为调度程序不得不将处理器时间在多个活动线程之间分割。 服务器的目标是使线程避免不必要的阻塞,尽量减少上下文切换。同时,还要使用多线程来发挥最大限度的并行。理想的情况是在每一个处理器上运行一个线程来处理一个客户请求,当处理器上的活动线程完成一个请求时,如果还有其他的请求正在等待,则不阻塞。为了使这一优化处理可以有效的进行,应用程序必须有一种可行的方法,使得一个正在处理客户请求的线程在I/O上阻塞时(例如它在处理过程中需要读取一个文件时)另外一个等待线程被激活。 Windows NT 3.5引进了一系列API使得这个目标的实现变得相对容易。这些API主要聚焦在一个叫完成端口的对象上。在本文中,首先我将讲解完成端口的使用,然后再深入其内部,向你展示Windows NT中完成端口的实现机制。 使用I/O完成端口 应用程序将IoCompletion执行体对象当作与多个文件句柄相关的I/O完成的核心。一旦一个文件与一个完成端口相关联,任何在此文件上异步I/O操作的完成都会导致一个完成通知包(completion notification packet)加入到完成端口队列。一个线程只需简单的等待一个完成通知包被排队到此完成端口上,就可以等待在多个文件上的所有正在进行之中的I/O操作的完成事件。Windows API中的WaitForMultipleObjects 提供了类似的功能,但完成端口的优点在于在系统的协助下发挥高效的并发性。这里的并发性可以理解为应用程序主动处理客户请求的线程的数量的多少。 当应用程序创建一个完成端口时,需要设定并发量。该数值指示了在任何给定时候正在运行的与该端口相关联的线程的最大数量。正如前面所提到的,理想情况是在任何给定的时刻,系统中每个处理器都有一个线程在运行。Windows利用与一个端口相关联的并发值参数来控制一个应用程序中活动线程的数量。如果与一个端口相关的活动线程数达到并发值,那么,在这个端口上等待的线程将不允许再运行了。相反,它将等待某个活动线程处理完当前操作并检查是否有别的包正在该端口上等待。如果有的话,该线程只是简单的抓获该包然后处理。在这个过程中,没有上下文切换,CPU得到最大限度的利用。 下图1显示了一个完成端口操作流程的高度图解。客户请求将导致一个I/O包(IRP)被排队到完成端口。操作系统允许不超过并发量上限(即上面提到的那个并发值)的多个线程并发地处理客户端请求。直到一些活动线程因I/O请求而阻塞,等待线程才能被激活。下面我们将做进一步的探讨。 图1 I/O完成端口操作流程 创建完成端口需要调用Windows API CreateIoCompletionPort: HANDLE CreateIoCompletionPort( HANDLE FileHandle, HANDLE ExistingCompletionPort, DWORD CompletionKey, DWORD NumberOfConcurrentThreads ); 创建一个完成端口时,通常对参数ExistingCompletionPort赋值NULL, NumberOfConcurrentThreads参数定义了在完成端口上同时允许执行的线程数量。如果有文件句柄传递给FileHandle参数,则该文件与完成端口关联在了一起。当这个文件上的I/O请求完成时,一个完成通知包将被投递到完成端口消息队列中。另外一个API GetQueuedCompletionStatus是用来获取排队完成状态,它使调用线程挂起,直到收到一个完成通知包。 BOOL GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, LPDWORD CompletionKey, LPOVERLAPPED* lpOverlapped, DWORD dwMiil

文档评论(0)

小教资源库 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档