IOCP Internals
Buffer Type
Buffer I/O
针对Buffer I/O的请求,系统会为其分配一个非换页内存作为缓存区,其大小等同于I/O请求的缓存区大小。对于写操作,I/O管理器在创建IRP时,将请求者的缓存区数据拷贝到申请得到的非换页缓存区中。对于读操作,I/O管理器将会在I/O完成时,将数据从非换页内存缓存区中拷贝到请求者的缓存区中。在I/O完成后,会释放掉该次申请到的非换页缓存区。
Direct I/O
I/O管理器在处理Direct I/O类型的请求时,会将请求者的缓存区锁定在内存中,使其变成不可换页的内存。当该I/O处理完成时,I/O管理器会解除请求者缓存区的锁定。I/O管理器用MDL机制锁定请求的缓存区,在需要操作缓存区的时候,可以使用相应的API映射请求者的缓存区到系统的地址空间。
Neither I/O
对于此种I/O请求,I/O管理器不会执行任何缓存区管理,对应的缓存管理交给相应的设备驱动程序自己处理。但是不管设备驱动程序如何处理,都不会超过上面两种方式的处理。
I/O Type
Synchronous I/O
应用程序发出的大部分I/O操作是同步的。在设备处理I/O请求时,应用程序需要一直等待,直到I/O完成时,设备返回结果,最终程序才可以继续执行。并且可以立即访问这些被传输的数据。
Asynchronous I/O
异步I/O是程序先发出一个I/O请求,交由设备处理,程序可以继续执行。该程序可以在处理其他事务后检查I/O是否完成,或者当I/O完成时,I/O管理器主动告诉程序I/O已完成。 为了在WINDOWS使用异步I/O,打开文件或建立SOCKET时,需要指定FILE_FLAG_OVERLAPPED标志。
在发起一个异步I/O请求后,必须十分小心:在I/O未完成时,不能访问该I/O操作中任何数据,要确保缓存区有效。发起异步I/O后,为了拿到最终有效的数据,需要做同步操作,WINDOWS下支持OVERLAPPED,也就是基于EVENT内核对象同步,APC(异步过程调用)还有IOCP(I/O Completion Port)。
I/O Completion Process
当一个设备处理完I/O请求时,会调用内核API IoCompleteRequest,通知I/O管理器自己完成了该I/O请求。为了安全操作用户的缓存区,I/O管理器会根据I/O请求类型会执行相应的动作:如果是同步I/O请求,那么可以直接操作请求的缓存区;如果是异步I/O请求,I/O管理器会延迟该I/O完成动作直到请求者对应的地址空间为止。完成该动作的方式是向该请求的线程投递一个APC。在切换到该请求的I/O请求所在的线程时,该APC会得到执行。会把已完成的I/O请求中得到的数据拷贝到对应的缓存区中。这个时候,对于异步I/O请求,像ReadFileEx/WriteFileEx可以投递一个APC例程,I/O管理器在执行I/O完成最后一步后,检测到有APC,就把该APC例程投递到请求线程内,当线程处于警告状态时(SleepEx, WaitForSingleObjectEx)会得到执行。如果该异步I/O请求对应的文件对象或者SOCKET绑定了IOCP,则会在处理完成时,把对应的OVERLAPPED结构投递到IOCP队列中。 这也就是当处理WSARecv时(假设该请求的SOCKET已经绑定了IOCP),如果这个时候系统中已经缓存了数据,这个时候不需要判断是否接收到数据,而只需要判断LastError是否是ERROR_IO_PENDING的原因。
IOCP
在实现服务端程序时,常用的一个简单处理网络请求的方式是针对连接分配一个线程单独处理。太少或太多都会带来性能问题。线程太少,对于客户端的请求无法及时处理;太多,会导致线程频繁轮换。理想的情形是,在服务器的每个处理器上都有一个线程在积极的处理一个用户的请求,如果有其他的请求在等待的话,会立刻有线程来处理这些请求。为了达到这一最优过程得以最终正确的进行,需要有一个办法,能够在处理客户请求的线程在I/O阻塞时,能激活另一个线程处理其他请求。
WINDOWS中引入了IOCP机制来实现这一最优过程。IOCP的内部是依靠一个叫队列的内核对象完成这一过程。当创建一个文件句柄或者SOCKET时,可以把句柄与IOCP句柄绑定在一块,任何以此句柄发起的异步I/O请求操作在完成时都会生成一个CompletionPackage,并把该CompletionPackage排队到该完成端口上,也就是排队到内部的队列内核对象上。应用程序可以通过API GetQueuedCompletionStatus获取已完成的CompletionPackage,处理已完成的I/O数据。
WINDOWS API中的WaitForMultipleObjects函数提供了类似的功能,但是,完成端口的好处是,在系统协助下并发是可控的。处理方式是应用程序主动处理客户端请求的线程的数量。前面提到,理想情况是每个处理器都由一个线程在处理客户端请求。在创建IOCP时,会制定一个值,这个值为关注IOCP的线程数。因为IOCP的内部机制依赖于队列内核对象,在WINDOWS中,内核对象都是可等待的,也就是用类似WaitForSingleObject类似的机制。而IOCP在创建时制定的值会传给内部的队列内核对象作为一个并发值。如果与IOCP关联的活动线程的数量超过了这个并发值,那么正在该IOCP上等待的线程将不允许运行。当有异步I/O完成时,会投递CompletionPackage到绑定的IOCP中的队列对象中,如果此时有线程正在等待,则会直接把这个CompletionPackage交给这个正在等待的线程处理。这样的过程中,没有线程环境切换,更好的把CPU的能力利用起来。
关于IOCP的并发值,Microsoft的指导原则是,将并发值设置成大约等于该系统中处理器的数目。
参考文档:
- 《深入解析Windows操作系统第四版》
- Windows Research Kernel
IOCP Internals的更多相关文章
- iocp 小例子
2016-08-3116:44:09 server 端 /******************************************************************* aut ...
- 简单说一个IOCP不好的地方
感谢rulary的指正!博文中我对IOCP的理解是有误的,正确的方式请见评论区rulary的回复! 由于项目实际设计的需要,最终IO事件处理没有采用IOCP,而是采用了NT6.0引入的WSAPoll, ...
- IOCP和WSA异步协同客户端版
有些小伙伴看了之前发的WIN平台下IOCP和WSA异步协同处理SOCKET后有些疑惑,所以就画了个简易流程图+架构图发上来给小伙伴参考 简单说,WSA异步控制CONNECT,IOCP控制WSASend ...
- windows WSABUF 结构在IOCP 中应用时两个成员变量的意义
WSABUF 结构的原型如下: typedef struct __WSABUF { u_long len; char FAR *buf; } WSABUF, *LPWSABUF; 该结构在IOCP 中 ...
- IOCP入门
完成端口(Completion Port)详解 此文讲解最好,也很全面一下其他文章看看就行,也可不看. 单句柄数据,单IO数据 此文讲述比较清晰,可以辅助理解上文. IOCP编程之基本原理:http: ...
- 解剖SQLSERVER 完结篇 关于Internals Viewer源代码
解剖SQLSERVER 完结篇 关于Internals Viewer源代码 大家可能都用过Internals Viewer这个软件 <查看SQLSERVER内部数据页面的小插件Internals ...
- Key Components and Internals of Spring Boot Framework--转
原文地址:http://www.journaldev.com/7989/key-components-and-internals-of-spring-boot-framework In my prev ...
- iocp还是select
上一个项目libevent应该是select,现在libuv是iocp,都知道Windows下iocp比select效率高,boost asio 也是iocp,但具体使用select和iocp发现没有 ...
- 再谈select, iocp, epoll,kqueue及各种I/O复用机制
原文:http://blog.csdn.net/shallwake/article/details/5265287 首先,介绍几种常见的I/O模型及其区别,如下: blocking I/O nonbl ...
随机推荐
- 【SQLServer】【恢复挂起的解决方案】附加文件时候的提示“无法重新生成日志,原因是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。 ”【数据库恢复】
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 先贴错误: 吐槽一下: 进入正题: 新建一个同名数据库 停止MSSQL服务 替换数据库文 ...
- C++中的引用
一,C++中引用的基础知识 1.引用的基本概念 1.所谓的引用其实就是对变量起“别名”.引用和变量对应得是相同的内存,修改引用的值,变量的值也会改变,和指针类似. 2.引用在定义的时候必须要初始化,初 ...
- 【开源】.Net Api开放接口文档网站
开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务 238543768 ApiView .net api的接口文档查看 ...
- Asp.net Core 初探(发布和部署Linux)
前言 俗话说三天不学习,赶不上刘少奇.Asp.net Core更新这么长时间一直观望,周末帝都小雨,宅在家看了下Core Web App,顺便搭建了个HelloWorld环境来尝尝鲜,第一次看到.Ne ...
- 微软开源代码编辑器monaco-editor
官网上给出:”The Monaco Editor is the code editor that powers VS Code. A good page describing the code edi ...
- 在Mac OS X上安装ASP.NET 5(译文)
ASP.NET 5 运行在包括OS X的可用于多个平台的.NET Execution Environment(DNX)上.本文介绍如何在OS X上通过HomeBrew安装DNX和ASP.NET 5. ...
- 微软开源全新的文档生成工具DocFX
微软放弃Sandcastle有些年头了,微软最近开源了全新的文档生成工具DocFX,目前支持C#和VB,类似JSDoc或Sphinx,可以从源代码中提取注释生成文档之外,而且还有语法支持你加入其他的文 ...
- 保护ASP.NET 应用免受 CSRF 攻击
CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/ ...
- 淘宝UWP中的100个为什么
从淘宝UWP第一版发布到现在,已经有十个月了,期间收到了用户各种各样的反馈,感谢这些用户的反馈,指导我们不断的修正.完善应用.但是也有一部分需求或建议,由于资源或技术的限制,目前确实无法做到,只能对广 ...
- Nodejs之MEAN栈开发(六)---- 用Angular创建单页应用(上)
在上一节中我们学会了如何在页面中添加一个组件以及一些基本的Angular知识,而这一节将用Angular来创建一个单页应用(SPA).这意味着,取代我们之前用Express在服务端运行整个网站逻辑的方 ...