【重叠I/O之系列三】I/O完成端口
一 串行模式和并行模式
一般一个服务应用程序采用以下两个架构模型之一:
- 串行模式 一个线程等待一个客户发出的请求,当请求到达的时候,线程会被换醒来处理客户的请求。
- 并发模式。一个线程等待一个客户发出的请求,当请求到达的时候,线程会创建一个新的线程来处理客户的请求,而当前线程则会进入下一次循环继续等待客户的请求。
在当前多客户请求的环境下,串行模式远远不能满足当前服务器的性能要求。串行模式每次只能处理一个客户请求,而现在的计算机大多数都是多处理器的机器,所以不充分发挥出多处理器机器的优势。所以串行模式只能应用于一些简单的服务器应用程序,向Ping服务器程序。
由于串行模式的受限,所以在服务器应用中一般采用并发模式。在并发模式中,当服务器接受到一个客户请求时,会创建一个新的线程来处理客户请求。这种模式的优点是显而易见的,等待请求的线程只有很少的工作需要做。当客户请求到达的时候,该线程会被唤醒,创建一个新的处理线程,然后继续睡大觉。所以,服务器可以很快的对客户请求进行相应。而同时,每个客户请求都有一个线程来对其进行处理,能够发挥多处理器机器的优势。但是,这并不是没有缺点的:当一个机器中的线程远大于处理器的数目时,频繁的线程切换会极大的浪费CPU的性能。例如,如果有2000个客户请求,当前的并发模型就需要2000个线程来处理请求,每个线程都需要大量的虚拟内存空间。系统默认的每个线程消耗1MB的堆栈空间,则2000个线程消耗2G虚拟地址空间,而且线程上下文的切换会增加页错误,同时会CPU在线程的上下文切换上需要浪费太多的时间,而线程真正得到CPU执行时间很少。同时,虽然创建一个线程的开销相对于创建进程小的多,但是它的开销仍然不小。如果应用程序能够在初始化的时候创建一个线程池,这样当需要调用线程的时候直接从线程池中获取,这样便可以大大的提升性能了。
正是为了解决以上问题,Windows提出了I/O完成端口解决方案,使得我们在线程池中创建有限数量的服务器线程,这个线程池的调用由Windows系统来维护。同时使用大量的套接字或命名管道句柄,让每个句柄都与不通的客户相关联,句柄不和服务器线程配对。当一个重叠的I/O完成后,会被加入到完成队列中,系统会从线程池中唤醒一个线程来处理完成的I/O请求。
二 I/O完成端口解析
1 创建I/O完成端口
创建I/O完成端口调用函数:
HANDLE
WINAPI
CreateIoCompletionPort(
__in HANDLE FileHandle,
__in_opt HANDLE ExistingCompletionPort,
__in ULONG_PTR CompletionKey,
__in DWORD NumberOfConcurrentThreads
);
- FileHandle
FileHandle是要添加到端口中的一个重叠的设备句柄,注意一个I/O完成端口是以OVERLAPPED模式打开的文件句柄的集合。如果创建一个新的I/O完成端口,则此值为INVALID_HANDLE_VALUE,同时参数ExistingCompletionPort为空。
- ExistingCompletionPort
ExistingCompletionPort表示文件句柄将要关联的端口。
- CompletionKey
CompletionKey指定在完成包中为FileHandle所包含的键值。这个键值可以指向一个结构的指针,该结构包含包含了诸如操作类型、句柄以及指向数据缓冲区指针等信息。
- NumberOfConcurrentPort
表示允许并发执行的线程的最大数量,超过这个数量的等待端口的线程将保持阻塞状态。如果为0,那么最大的并发执行的线程数就是系统中处理器的数目。当ExistingCompletionPort不为NULL时,这个值会被忽略。
这个函数其实是完成两个任务:一是创建一个I/O完成端口,二是将一个设备与一个I/O完成端口关联起来。只是该函数将所有的参数放到一起,显得有点复杂。我们可以将其进行功能拆分,创建两个小函数来分别完成以上两个任务:
//创建新的I/O完成端口
HANDLE CreateNewCompletionPort(DWORD dwNumOfConcurrentThread)
{ return CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, , dwNumOfConcurrentThread);
} //将设备和IO完成端口相关联
BOOL AssociateDeviceWithCompletionPort(HANDLE hDevice, HANDLE hCompletionPort, DWORD dwCompKey)
{
HANDLE h = CreateIoCompletionPort(hDevice,hCompletionPort,dwCompKey,);
return (h == NULL);
}
【重叠I/O之系列三】I/O完成端口的更多相关文章
- 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家
系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...
- Web 开发人员和设计师必读文章推荐【系列三十】
<Web 前端开发精华文章推荐>2014年第9期(总第30期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
- MySQL并发复制系列三:MySQL和MariaDB实现对比
http://blog.itpub.net/28218939/viewspace-1975856/ 并发复制(Parallel Replication) 系列三:MySQL 5.7 和MariaDB ...
- WCF编程系列(三)地址与绑定
WCF编程系列(三)地址与绑定 地址 地址指定了接收消息的位置,WCF中地址以统一资源标识符(URI)的形式指定.URI由通讯协议和位置路径两部分组成,如示例一中的: http://loc ...
- 【JAVA编码专题】 JAVA字符编码系列三:Java应用中的编码问题
这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...
- SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型
原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...
- VSTO之旅系列(三):自定义Excel UI
原文:VSTO之旅系列(三):自定义Excel UI 本专题概要 引言 自定义任务窗体(Task Pane) 自定义选项卡,即Ribbon 自定义上下文菜单 小结 引言 在上一个专题中为大家介绍如何创 ...
- 系列三VisualSvn Server
原文:系列三VisualSvn Server VisualSvn Server介绍 1 .VisualSvn Server VisualSvn Server是免费的,而VisualSvn是收费的.V ...
随机推荐
- A Tour of Go Range continued
You can skip the index or value by assigning to _. If you only want the index, drop the ", valu ...
- 转载ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction区别
对这四个的区别做一个总结,清理一下思路,方便以后使用: 1.带有Render的方法返回值是void,在方法内部进行输出:不带的返回值类型为MvcHtmlString,所以只能这样使用: @Ht ...
- 转载 ASP.NET MVC中使用ASP.NET Identity
转载原地址: http://blog.jobbole.com/90695/ 在之前的文章中,我为大家介绍了OWIN和Katana,有了对它们的基本了解后,才能更好的去学习ASP.NET Identit ...
- FreeModbus Slave 改进的eMbPoll()【worldsing 笔记】
eMbPoll()的作用是FreeMod协议通信过程中不断查询事件对列有无完速数据桢,并进行地址和CRD验证,最后运行和回复主机. 为了减小代码尺寸对eMbPoll进行改进: 原版: 1: 2: e ...
- Codeforces 390Div2-754D. Fedor and coupons(贪心+优先队列)
D. Fedor and coupons time limit per test 4 seconds memory limit per test 256 megabytes input standar ...
- byte数组和int互转
import java.nio.ByteBuffer; public class Program { public static void main(String[] args) { ByteBuff ...
- 如何在64位系统上安装SQL Server 2000
如何在64位系统上安装SQL Server 2000? 现在用SQL Server 2000数据库的人少了吧?大都是SQL Server 2005/2008了.不过还是有需求的,今天一朋友就让我在他的 ...
- struts中的helloword(1)
注:文章中的所有图片均在附件中明白表明 首先要安装jdk1.6以及tomcat6和myeclipse 对于这些配置的安装 这里不再细细说明 其次是下载struts2 第一步:去struts21 ...
- C++ 构造过程和析构过程
1.C++构造和析构的过程,类似于穿衣脱衣的过程.穿衣是:先穿内衣,再穿外套.脱衣是:先脱外套,再脱内衣.C++构造过程:首先调用父类构造方法,再调用子类构造方法.C++析构过程:首先调用子类析构方法 ...
- oracle查询前10条记录
select * from table_name where rownum<11;