一、IOCP(I/O Completion Ports)简介

       要实现异步通信,必须要用到一个很风骚的I/O数据结构 ,叫重叠结构“Overlapped”,Windows里所有的异步通信都是基于它的,完成端口也不例外。

      Overlapped重叠结构 这里可以简单的将其理解为一个操作系统和用户之间的参数传递变量,属于“单IO数据”的一部分)

(这张图是个人自己的理解,这两张图结合起来看)

当我们创建一个I/O完成端口的时候,系统内核实际上会创建5个不同的数据结构。

I/O完成端口如何管理线程池

现在是讨论I/O完成端口为什么如此有用的时候了。首先,当我们创建I/O完成端口的时候,需要指定允许多少个线程并发运行(此时并没有创建线程池)。正如前面已经提到过,我们通常会将这个值设为主机的CPU数量。当已完成的I/O项被添加到队列中的时候,I/O完成端口想要唤醒正在等待的线程。但是,完成端口唤醒的线程数量最多不会超过我们指定的数量。因此,如果有4个I/O请求已完成,有4个线程正在等待GetQueuedCompletionStatus,那么I/O完成端口只会唤醒两个线程,而让其他两个线程继续睡眠。当每个线程处理完-一个已完成的I/O项时,会再次调用GetQueuedCompletionStatus. 这时系统发现队列中还有其他的项,于是会唤醒同一个线程来对剩余的项进行处理。

如果读者仔细考虑一 下,就应该注意到有些东西没有太大的意义。如果完成端口只允许同时唤醒指定数量的线程,那么为什么还要让更多的线程在线程池中等待呢?举个例子,假设我们正在一台有两个CPU的机器上运行,我们创建了一个I/O完成端口,并告诉它同时最多只能有两个线程来处理已完成的项。但我们在线程池中创建了4个线程(是CPU数量的两倍)。看起来似乎我们创建了两个多余的线程,它们永远都不会被唤醒来处理任何东西。

但I/O完成端口是非常智能的。当完成端口唤醒一个线程的时候,会将该线程的线程标识符保存在与完成端口相关联的第4个数据结构中,也就是已释放线程列表(released thread list)。这使得完成端口能够记住哪些线程已经被唤醒,并监视它们的执行情况。如果一个已释放的线程调用的任何函数将该线程切换到了等待状态,那么完成端口会检测到这一情况,此时它会更新内部的数据结构,将该线程的线程标识符从已释放线程列表中移除,并将其添加到已暂停线程列表(paused thread list)中(与I/O完成端口相关联的第5个也是最后一个数据结构)。

完成端口的目标是根据在创建完成端口时指定的并发线程的数量,将尽可能多的线程保持在已释放线程列表中。如果一个已释放线程由于任何原因而进入等待状态,那么已释放线程列表会缩减,完成端口就可以释放另一个正在等待的线程。如果一个 已暂停的线程被唤醒,那么它会离开已暂停线程列表并重新进入已释放线程列表。这意味着此时已释放线程列表中的线程数量将大于最大允许的并发线程数量。

让我们把这些总结一下。 假设我们在一 台有两个CPU的机器上运行。我们创建了一个同时最多只允许两个线程被唤醒的完成端口,还创建了4个线程来等待己完成的IO请求。如果3个已完成的IO请求被添加到端的队列中,只有两个线程会被唤醒来对请求进行处理,这降低了可运行线程的数量,并节省了上下文切换的时间。现在,如果一个可运行线程调用了Sleep,WaitForSingleObject,WaitForMultipleObjects,SignalObjectAndWait,一个异步 I/O调用或任何能够导致线程变成不可运行状态的函数, I/O 完成端口会检测到这一情况并立即唤醒第3个线程。完成端口的目标是使CPU保持在满负荷状态下工作。

最后,第一个线程将再次变成可运行状态。当发生这种情况的时候,可运行线程的数量将超过系统中CPU的数量。但是,完成端口仍然知道这一点, 在线程数量降到低于CPU数量之前,它是不会再唤醒任何线程的。I/O完成端口体系结构假定可运行线程的数量只会在很短一段时间内高于最大允许的线程数量,一旦线程进入下一次循环并调用GetQueuedCompletionStatus,可运行线程的数量就会迅速下降。这就解释了为什么线程池中的线程数量应该大于在完成端口中设置的并发线程数量。

IOCP 用来进行线程间通信

I/O完成端口是一项非常棒的技术,并不一定要用于设备I/O还可以用来进行线程间通信。I/O 完成端口有一个函数,名叫PostQueuedCompletionStatus:

IOCP(I/O Completion Port,I/O完成端口)是Windows操作系统中伸缩性最好的一种I/O模型。
    I/O 完成端口是应用程序使用线程池处理异步 I/O 请求的一种机制。处理多个并发异步I/O请求时,使用 I/O 完成端口比在 I/O 请求时创建线程更快更高效。
二、IOCP的优势

    I/O 完成端口可以充分利用 Windows 内核来进行 I/O 调度,相较于传统的 Winsock 模型,IOCP 在机制上有明显的优势。

    相较于传统的Winsock模型,IOCP的优势主要体现在两方面:独特的异步I/O方式和优秀的线程调度机制。

独特的异步I/O方式

    IOCP模型在异步通信方式的基础上,设计了一套能够充分利用Windows内核的I/O通信机制,主要过程为:① socket关联iocp,② 在socket上投递I/O请求,③ 事件完成返回完成通知封包,④ 工作线程在iocp上处理事件。

    IOCP的这种工作模式:程序只需要把事件投递出去,事件交给操作系统完成后,工作线程在完成端口上轮询处理。该模式充分利用了异步模式高速率输入输出的优势,能够有效提高程序的工作效率。

优秀的线程调度机制

    完成端口可以抽象为一个公共消息队列,当用户请求到达时,完成端口把这些请求加入其抽象出的公共消息队列。这一过程与多个工作线程轮询消息队列并从中取出消息加以处理是并发操作。这种方式很好地实现了异步通信和负载均衡,因为它使几个线程“公平地”处理多客户端的I/O,并且线程空闲时会被挂起,不会占用CPU周期。
    IOCP模型充分利用Windows系统内核,可以实现仅用少量的几个线程来处理和多个client之间的所有通信,消除了无谓的线程上下文切换,最大限度的提高了网络通信的性能。

【C# 线程】IOCP IO完成端口-Windows系统下常见的7种I/O模型的更多相关文章

  1. 【C# 线程】Windows系统下常见的7种I/O模型 之Overlapped I/O模型

    overview 这个字符到底是什么含义呢?其实它的意思就是当程序在等待设备操作的时候,可以继续往下做而不必阻塞到那个地方等待设备操作的返回,这就造成了程序运行和设备操作时间上的重叠.  Overla ...

  2. windows系统下npm升级的正确姿势以及原理

    本文来自网易云社区 作者:陈观喜 网上关于npm升级很多方法多种多样,但是在windows系统下不是每种方法都会正确升级.其中在windows系统下主要的升级方法有以下三种: 首先最暴力的方法删掉no ...

  3. windows系统下在dos命令行kill掉被占用的pid (转)

    原文出自:http://www.2cto.com/os/201304/203771.html   windows系统下在dos命令行kill掉被占用的pid   1.开始-->运行-->c ...

  4. windows系统下安装MySQL

    可以运行在本地windows版本的MySQL数据库程 序自从3.21版以后已经可以从MySQL AB公司获得,而且 MYSQL每日的下载百分比非常大.这部分描述在windows上安装MySQL的过程. ...

  5. Windows系统下Memcached缓存系列二:CouchbaseClient(c#客户端)的详细试用,单例模式

    在上一篇文章里面 ( Windows系统下Memcached缓存系列一:Couchbase(服务器端)和CouchbaseClient(c#客户端)的安装教程 ),我们介绍了服务器端的安装和客户端的安 ...

  6. Windows系统下Nginx的安装与配置

    Nginx是lgor Sysoev在2004年的时候为俄罗斯访问量第二大的rambler.ru站点设计开发的,发布至今,凭借开源的力量,已经接近成熟与完善.其功能丰富,可作为HTTP服务器,也可作为反 ...

  7. Windows系统下的TCP参数优化(注册表\TCPIP\Parameters)

    转自:https://blog.csdn.net/libaineu2004/article/details/49054261 Windows系统下的TCP参数优化   TCP连接的状态与关闭方式及其对 ...

  8. Tomcat Windows 系统下安装及注意事项

    1 获取Tomcat 安装包  http://tomcat.apache.org/ tar.gz 文件是Linux系统下的安装版本 exe文件是 Windows系统下的安装版本 zip 文件是Wind ...

  9. Windows系统下安装zabbix客户端

    简单介绍如何在windows系统下安装zabbix客户端 1. 首先下载和zabbix服务端大版本相同的windows客户端    例如我服务端安装的是zabbix-3.4.14.tar.gz     ...

随机推荐

  1. WSL与gnome-desktop

    WSL与gome-desktop 经过测试和检索 确定WSL1无法在gome-desktop实现GUI桌面 只能实现其中应用的现实,比如打开记事本在Xserver https://www.reddit ...

  2. 推荐召回--基于物品的协同过滤:ItemCF

    目录 1. 前言 2. 原理&计算&改进 3. 总结 1. 前言 说完基于用户的协同过滤后,趁热打铁,我们来说说基于物品的协同过滤:"看了又看","买了又 ...

  3. java-导入import

    1 package face_package; 2 3 import face_packagedemoA.DemoA; 4 import face_packagedemoB.DemoB; 5 //真正 ...

  4. jetson-nano opencv基础使用

    前言: jetson nano前一篇给大家介绍了学习的一些思路和资料,今天继续给大家分享一篇在jetson nano使用opencv的文章. OpenCV的全称是Open Source Compute ...

  5. AT2164 [AGC006C] Rabbit Exercise

    首先我们可以考虑一下 \(x\) 关于 \(y\) 的对称点的坐标,不难发现就是 \(x + 2 \times (y - x)\),那么期望的增量就会增加 \(2 \times (y - x)\).不 ...

  6. 实现表单input文本框不可编辑的三种方法

    感谢原文作者:青灯夜游 原文链接:https://www.php.cn/div-tutorial-413133.html 目录 问题 实现方式 1.οnfοcus=this.blur() 2.read ...

  7. winform 获得局域网内在线IP和计算机名,获取IP,多线程网络编程

    转载请注明来源:https://www.cnblogs.com/hookjc/ using System; using System.Collections.Generic; using System ...

  8. XML 中如何输入回车换行

    XML 中如何输入回车换行? XML 特殊字符: 下面的字符在 [XML]中被定义为 空白(whitespace)字符: 空格 ( ) Tab ( ) 回车 ( ) 换行 ( ) XML 中如何输入回 ...

  9. Java使用DOM方式读写XML

    一.DOM读取 import ***; public class ReadXML { public static void main(String[] args) { try { //DOM Docu ...

  10. 重新认识Appium

    一.重新认识Appium   找到了学习资料,却不知道怎么实现!!! 要如何实现呢? Appium完整案例值得参考:手把手搭建环境,其中安装和配置Mave这部分有点老了. 首先下载maven 官网地址 ...