一   串行模式和并行模式

  一般一个服务应用程序采用以下两个架构模型之一:

  • 串行模式  一个线程等待一个客户发出的请求,当请求到达的时候,线程会被换醒来处理客户的请求。
  • 并发模式。一个线程等待一个客户发出的请求,当请求到达的时候,线程会创建一个新的线程来处理客户的请求,而当前线程则会进入下一次循环继续等待客户的请求。

  在当前多客户请求的环境下,串行模式远远不能满足当前服务器的性能要求。串行模式每次只能处理一个客户请求,而现在的计算机大多数都是多处理器的机器,所以不充分发挥出多处理器机器的优势。所以串行模式只能应用于一些简单的服务器应用程序,向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完成端口的更多相关文章

  1. 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家

    系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...

  2. Web 开发人员和设计师必读文章推荐【系列三十】

    <Web 前端开发精华文章推荐>2014年第9期(总第30期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  3. MyBatis学习系列三——结合Spring

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...

  4. MySQL并发复制系列三:MySQL和MariaDB实现对比

    http://blog.itpub.net/28218939/viewspace-1975856/ 并发复制(Parallel Replication) 系列三:MySQL 5.7 和MariaDB ...

  5. WCF编程系列(三)地址与绑定

    WCF编程系列(三)地址与绑定   地址     地址指定了接收消息的位置,WCF中地址以统一资源标识符(URI)的形式指定.URI由通讯协议和位置路径两部分组成,如示例一中的: http://loc ...

  6. 【JAVA编码专题】 JAVA字符编码系列三:Java应用中的编码问题

    这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...

  7. SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型

    原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...

  8. VSTO之旅系列(三):自定义Excel UI

    原文:VSTO之旅系列(三):自定义Excel UI 本专题概要 引言 自定义任务窗体(Task Pane) 自定义选项卡,即Ribbon 自定义上下文菜单 小结 引言 在上一个专题中为大家介绍如何创 ...

  9. 系列三VisualSvn Server

    原文:系列三VisualSvn Server VisualSvn Server介绍 1 .VisualSvn Server  VisualSvn Server是免费的,而VisualSvn是收费的.V ...

随机推荐

  1. 使用Intent在活动之间穿梭(《第一行代码》读书笔记)

    以下全是个人理解//瞎扯 其实活动理解理解起来就像一个个函数 那么Intent就是调用函数和参数传递 可以有无参,仅仅是调用 Intent intent = new Intent(A.this, B. ...

  2. python 偏函数

    functools.partial可以设置默认参数和关键字参数的默认值 Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function).要注意,这里的 ...

  3. Cookie与Session的初探

    1.Cookie 2.Session 每当一个新的请求来时,asp.net会根据浏览器有没传来SessionId(一般用Cookie传过来的,也可以用url传),来判断是新创建一个session还是根 ...

  4. android系统自带图标集合(android.R.drawable查看)

    alert_dark_frame alert_light_frame arrow_down_float arrow_up_float bottom_bar btn_default btn_defaul ...

  5. C++学习笔记(四):枚举

    枚举用来代替静态常量,优点就是可以确定值的范围,而常量则无法确定范围: 常量表示法: ; ; ; ; ; bool func(int type) { //范围检查 || type > ) thr ...

  6. Flask 框架下 Jinja2 模板引擎高层 API 类——Environment

    Environment 类版本: 本文所描述的 Environment 类对应于 Jinja2-2.7 版本.   Environment 类功能: Environment 是 Jinja2 中的一个 ...

  7. mysql服务的启动和停止 net stop mysql net start mysql

    第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名-p用户密码 键入命令mysql -uroo ...

  8. 单点登录系统CAS筹建及取得更多用户信息的实现

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  9. 逗号分隔字符串转换为一张表--解决查询in(逗号分隔字符串)出错问题

    CREATE PROCEDURE [dbo].[Pro_TEST] AS BEGIN ) ) SET @split=',' SET @c='025,023,014,015' )) ) BEGIN IN ...

  10. C#WinForm应用程序实现自动填充网页上的用户名和密码并点击登录按钮【转载】

    使用WebBrowser控件,在documentComplete事件处理器里写 HtmlElement name = webBrowser1.Document.GetElementById(" ...