【C# 线程】IOCP IO完成端口-Windows系统下常见的7种I/O模型
一、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模型的更多相关文章
- 【C# 线程】Windows系统下常见的7种I/O模型 之Overlapped I/O模型
overview 这个字符到底是什么含义呢?其实它的意思就是当程序在等待设备操作的时候,可以继续往下做而不必阻塞到那个地方等待设备操作的返回,这就造成了程序运行和设备操作时间上的重叠. Overla ...
- windows系统下npm升级的正确姿势以及原理
本文来自网易云社区 作者:陈观喜 网上关于npm升级很多方法多种多样,但是在windows系统下不是每种方法都会正确升级.其中在windows系统下主要的升级方法有以下三种: 首先最暴力的方法删掉no ...
- windows系统下在dos命令行kill掉被占用的pid (转)
原文出自:http://www.2cto.com/os/201304/203771.html windows系统下在dos命令行kill掉被占用的pid 1.开始-->运行-->c ...
- windows系统下安装MySQL
可以运行在本地windows版本的MySQL数据库程 序自从3.21版以后已经可以从MySQL AB公司获得,而且 MYSQL每日的下载百分比非常大.这部分描述在windows上安装MySQL的过程. ...
- Windows系统下Memcached缓存系列二:CouchbaseClient(c#客户端)的详细试用,单例模式
在上一篇文章里面 ( Windows系统下Memcached缓存系列一:Couchbase(服务器端)和CouchbaseClient(c#客户端)的安装教程 ),我们介绍了服务器端的安装和客户端的安 ...
- Windows系统下Nginx的安装与配置
Nginx是lgor Sysoev在2004年的时候为俄罗斯访问量第二大的rambler.ru站点设计开发的,发布至今,凭借开源的力量,已经接近成熟与完善.其功能丰富,可作为HTTP服务器,也可作为反 ...
- Windows系统下的TCP参数优化(注册表\TCPIP\Parameters)
转自:https://blog.csdn.net/libaineu2004/article/details/49054261 Windows系统下的TCP参数优化 TCP连接的状态与关闭方式及其对 ...
- Tomcat Windows 系统下安装及注意事项
1 获取Tomcat 安装包 http://tomcat.apache.org/ tar.gz 文件是Linux系统下的安装版本 exe文件是 Windows系统下的安装版本 zip 文件是Wind ...
- Windows系统下安装zabbix客户端
简单介绍如何在windows系统下安装zabbix客户端 1. 首先下载和zabbix服务端大版本相同的windows客户端 例如我服务端安装的是zabbix-3.4.14.tar.gz ...
随机推荐
- WSL与gnome-desktop
WSL与gome-desktop 经过测试和检索 确定WSL1无法在gome-desktop实现GUI桌面 只能实现其中应用的现实,比如打开记事本在Xserver https://www.reddit ...
- entity framework无法写入数据库.SaveChanges()失败
参考https://stackoverflow.com/questions/26745184/ef-cant-savechanges-to-db/28256645 https://www.codepr ...
- cesium流动纹理
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 之 ...
- C++模板之成员模板和模板构造函数
namespace myspace6 { template<typename T1> class TC { public: template<typename T2> TC(T ...
- javaObject类—getClass方法
1 package face_object; 2 /* 3 * Object:所有类的根类. 4 * Object是不断抽取而来的,具备所有对象都具备的共性内容. 5 * 常用的共性功能: 6 * 7 ...
- APC 篇—— APC 挂入
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- from 表单上传文件和下载?
from表单上传单个文件的方法. 分为三个部分,简单演示. 一部分 表单上传文件 <%-- Created by IntelliJ IDEA. User: Administrator Date: ...
- AT2400 [ARC072B] Alice&Brown
通过打表后可以发现,当初始石头数 \(|X - Y| \le 1\) 时先手必败否则先手必胜. 我们考虑使用归纳证明这个结论,显然 \((1, 0), (1, 1)\) 时是成立的. 基于观察,我们可 ...
- 连接mysql出现“Unable to load authentication plugin 'caching_sha2_password”错误
这是mysql 8.0版本才出现的问题,原因是mysql 8.0 默认使用 caching_sha2_password 身份验证机制 -- 从原来的 mysql_native_password 更改为 ...
- python folium 库学习
一.简介 folium是js上著名的地理信息可视化库leaflet.js为Python提供的接口,通过它,我们可以通过在Python端编写代码操纵数据,来调用leaflet的相关功能,基于内建的osm ...