当前位置:首页 > 物联网 > 《物联网技术》杂志
[导读]摘 要:介绍了Windows最复杂的内核对象IOCP (I/O Completion Port输入/输出完成端口)的基本原理。利用完成端 口机制,应用程序能够为数百上千的用户服务。文章通过完成端口对象指定一定数量的线程,对重叠I/O请求进行管理,从而 为已完成的重叠I/O请求提供服务。通过该模型编写的网络服务应用程序可以达到较好的性能。

引言

与计算机执行的大多数其他操作相比,设备I/O是其中 最慢、最不可预测的操作之一。比如CPU从硬盘文件中读写、 网络读取数据等,每一线程要等待I/O操作完成再执行后续 的代码。让太多或者太少的服务器线程来处理线程,都可能 会导致性能问题。使用异步设备I/O可以将请求交给设备的 驱动程序去处理,应用程序的线程可以执行其他有用的任务。 这样可以更好地使用资源并创建出更高效的应用程序。

但是,随着客户端请求、退出的增加,会有许多的并发 线程并发执行。由于这些线程都是可运行状态,Windows内 核会浪费太多时间来进行活动线程的上下文切换,如不断新 建和销毁线程。Windows提供了 I/O完成端口机制可以很好 地解决上述问题。

IOCP模型

当我们创建一个I/O完成端口的时候,系统内核实际上 会创建5个不同数据结构。完成端口会将客户请求加入到一 个公共的消息队列中,然后应用程序会创建一个线程池来处 理客户的请求。当设备与I/O完成端口相关联后,系统会检查 是否有与设备相关的一个I/O端口,若有则会将已完成的I/O 请求追加到消息队列,并调用相关的工作线程来处理这个请求。 当这个请求被处理完后,系统会通过一种机制通知客户,客户 只需要取处理好的数据即可。图1所示是一个完成端口模型 的结构示意图。

IOCP模型的使用

在实现异步通信机制的时候,一般要用到一个核心数据 结构重叠(OVERLAPPED)结构。OVERLAPPED结构定义

如下:

typedef struct _OVERLAPPED

{

DWORD Internal ;//[out]保存已处理的I/O请求的错误码 DWORD InternalHigh ; //[out]异步I/O完成保存已传输的字 节数

DWORD Offset ; //[int]文件传送的字节偏移量的低位字 DWORD OffsetHigh ;//[int]文件传送的字节偏移量的高位字 HANDLE hEvent ; //[in]指定一个I/O操作完成后触发的事件 [OVERLAPPED, *LPOVERLAPPED ;

OVERLAPPED结构执行两个重要的功能:第一,它像 一把钥匙,用以识别每一个目前正在进行的overlapped操 作,比如在网络发送和接收数据时,都会用到WSASend()和 WSARecv。函数,参数里面都会附带一个重叠结构,这个重 叠结构我们可以理解为一个网络操作的ID号,通过这个ID 号就可以区分是对哪个网络进行操作了;第二,它在你和系统 之间提供了一个共享区域,参数可以在该区域中双向传递。

基于完成端口模型的应用程序实现

2.1创建I/O完成端口

_inHANDLEFileHandle,

_in_optHANDLEExistingCompletionPort,

_inULONG_PTRCompletionKey,

_inDWORDNumberOfConcurrentThreads);

PULONG_PTRlpCompletionKey,//当文件I/O操作完成后,用于存放与之关联的CK(套接字信息结构体指针)

LPOVERLAPPED*lpOverlapped,//为调用IOCP机制所引用的OVERLAPPED结构

DWORDdwMilliseconds,//用于指定调用者等待

该函数用于创建一个完成端口对象和将一个句柄同完成CP的时间

端口关联在一起。在创建一个完成端口时,前三个参数都会忽);

略,NumberOfConcurrentThreads参数指定允许有多少线程处于可运行状态。通常给NumberOfConcurrentThreads参数当一^工作者线程从GetQueuedCompletionStatus调用中接收到I/O完成通知后,在lpCompletion和lpOverlapped参

设为0,那么I/O完成端口会使用默认值,也就是允许并发执数中,会包含一些必要的套接字信息。利用这些信息,可通

行的线程数量等于主机的CPU数量,避免额外的上下文切换。

过完成端口,继续在一个套接字上进行I/O处理。通过这些

代码如下:hIOCP=CreateIoCompletionPort(INVALID_HANDLE

VALUE,NULL,0,0);

2.2工作者线程和完成端口

成功创建一个完成端口后,便可开始将套接字句柄和对象关联到一起。但是在关联套接字之前,必须创建一个或多个工作者线程,以便在I/O请求投递完成端口对象后,为完成端口提供服务。应该创建多少个线程?在此要记住一个重点,在调用CreateIoCompletionPort时指定的并发线程数量,与打算创建的线程池线程数量是有区别的。假如在完成端口上创建的工作者线程数量超过指定并发执行的线性数量(这里设为n个),那么系统最多只允许n个线程运行。因为我们随时都能执行更多的线程,比如调用了函数Sleep或WaitForSingleObject使其处于暂停状态,就要用另外线程代替。为了充分发挥系统性能,一般设置为CPU的数量乘以2。

2.3完成端口与重叠I/O

创建好工作者线程后,调用GetQueuedCompletionStatus)函数让句柄和完成端口相关联起来,进行I/O请求处理。它将调用线程切换到睡眠状态,直到指定的完成端口的队列中出现该请求。如以套接字句柄为基础,投递数据发送和接收请求,会扫描完成端口的队列里是否有网络通信的请求存在(如读取数据、发送数据等),一旦发现消息队列中出现一项的时候,该完成端口会唤醒线性池中的一个线程。这个线程会得到已完成I/O项中的所有信息:

已传输的字节数、完成键以及OVERLAPPED结构的地址。GetQueuedCompletionStatus()函数定义如下:

BOOLGetQueuedCompletionStatus(

HANDLECompletionPort,//指定的IOCP,该值由CreateIoCompletionPort函数创建

LPDWORDlpNumberOfBytes,//一次完成后的I/O操作所传送数据的字节数

参数,可获得两种重要的套接字数据类型:单句柄数据以及单I/O操作数据。单I/O操作数据是CompletionKey(完成键)参数标识的是某个特定的套接字句柄数据,相当于用一个标志来绑定每一个I/O操作,这样收到网络操作完成的通知后,可以通过这个标志来找出返回的数据对应的I/O操作。该标志可以定义如下:

typedefstruct_PER_IO_CONTEXT{

OVERLAPPEDm_Overlapped;//每一^重叠I/O网络操作都要有一个

SOCKETm_sockAccept;//这个I/O操作所使用的Socket,每个连接的都是一样的

WSABUFm_wsaBuf;//存储数据的缓冲区,用来给重叠操作传递参数的

charm_szBuffer[MAX_BUFFER_LEN];//对应WSABUF里的缓冲区

OPERATION_TYPEm_OpType;//标志这个重叠1/O操作是做什么的,例如Accept/Recv等}PER_IO_CONTEXT,*PPER_IO_CONTEXT;

该结构关联了与I/O操作的某些重要数据元素,例如完成I/O操作发送或接受请求的类型m_OpType。每一个I/O操作对应了响应的PER_IO_CONTEXT,我们还要定义单句柄数据来管理句柄上的所有I/O请求,如在Socket上投递了多个AcceptEx请求,该结构定义如下:

typedefstruct_PER_SOCKET_CONTEXT{

SOCKETm_Socket;//每一个客户端连接的Socket

SOCKADDR_INm_ClientAddr;//这个客户端的地址

CArray<_PER_IO_CONTEXT*>m_arrayIoContext;//数组,所有客户端IO操作的参数,也就是说对于每一个客户端Socket是可以在上面同时投递多个IO请求的

2014年/第3期物联网技术61\}PER_SOCKET_CONTEXT,*PPER_SOCKET_CONTEXT;

2.4关闭IOCP

调用PostQueuedCompletionStatus函数,向每个工作者线程都发送一个特殊的完成数据包。可以唤醒那些还在等待完成端口但又没有已完成的I/O请求,每个线程会对GetQueuedCompletionStatus的返回值进行检查,如果发现应用程序正在终止,那么它就可以进行清理工作并正常的退出。

3IOCP程序流程

该程序调用高性能特性的AcceptEx函数用来完成端口异步,取消了阻塞方式的Accept调用。我们知道,AcceptEx是在客户端连入之前就把客户端的Socket建立好了,而不需要像Accept那样在客户端连入之后,再去时间去建立Socket。统可能来不及为更多的并发客户端现场准备Socket。另外,相比Accept只能阻塞方式建立一个连入接口而AcceptEx可以同时在完成端口上投递多个请求。图2所示是其程序的整体流程图。

基于完成端口模型的应用程序实现

4结语

采用I/O完成端口编写的服务应用程序,经过ProcessExplorer测试发现当服务器收到3000个并发线程的时候CPU占有率约为4%,而采用了多个并发线程的客户端程序CPU占有率约为12%。所以,如果预计到自己的服务器在任何给定的时间,都会为大量I/O请求提供服务,便应考虑使用I/O完成端口模型,从而获得更好的性能。但是在编写基于完成端口的系统创建一个Socket的开销是相当高了,用Accept的话,系服务应用程序时,还应注意重叠操作可确保按照应用程序安排好的顺序执行。然而,不能确保从完成端口返回的完成通知也按照上述顺序执行。在对数据包有要求的时候,比如传送大数据的时候,要注意这个顺序。

20211120_6197d4b147075__基于完成端口模型的应用程序实现

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭