完成端口(I/O completion)

完成端口与套接字绑定的OVERLAPPED结构释放问题 1楼  hxzb7215191   (天行健,君子以自强不息)  回复于 2005-01-09 11:56:56  得分 10 很简单的     只要这样         CloseHandle(m_ComPortItemArray[Index].ovRead.hEvent);         然后你使用之前需要把这个结构清空一次. Top2楼  kingzai 阅读详情

转自:http://blog.youkuaiyun.com/hyuantian/archive/2009/11/12/4801677.aspx

完成端口(I/O completion):

异步过程调用(apcs)问题:

    只有发overlapped请求的线程才可以提供callback函数(需要一个特定的线程为一个特定的I/O请求服务)。

 

完成端口(I/O completion)的优点:

    不会限制handle个数,可处理成千上万个连接。I/O completion port允许一个线程将一个请求暂时保存下来,由另一个线程为它做实际服务。

 

并发模型与线程池:

    在典型的并发模型中,服务器为每一个客户端创建一个线程,如果很多客户同时请求,则这些线程都是运行的,那么CPU就要一个个切换,CPU花费了更多的时间在线程切换,线程确没得到很多CPU时间。到底应该创建多少个线程比较合适呢,微软件帮助文档上讲应该是2*CPU个。但理想条件下最好线程不要切换,而又能象线程池一样,重复利用。I/O完成端口就是使用了线程池。

 

理解与使用:

第一步:

在我们使用完成端口之前,要调用CreateIoCompletionPort函数先创建完成端口对象。

定义如下:
HANDLE CreateIoCompletionPort(
                                HANDLE FileHandle,
                                HANDLE ExistingCompletionPort,
                                DWORD CompletionKey,
                                DWORD NumberOfConcurrentThreads
);
FileHandle
:

文件或设备的handle, 如果值为INVALID_HANDLE_VALUE则产生一个没有和任何文件handle有关系的port.( 可以用来和完成端口联系的各种句柄,文件,套接字)

ExistingCompletionPort:

NULL时生成一个新port, 否则handle会加到此port上。

CompletionKey:

用户自定义数值,被交给服务的线程。GetQueuedCompletionStatus函数时我们可以完全得到我们在此联系函数中的完成键(申请的内存块)。在GetQueuedCompletionStatus

中可以完封不动的得到这个内存块,并且使用它。

 

NumberOfConcurrentThreads:

参数NumberOfConcurrentThreads用来指定在一个完成端口上可以并发的线程数量。理想的情况是,一个处理器上只运行一个线程,这样可以避免线程上下文切换的开销。如果这个参数的值为0,那就是告诉系统线程数与处理器数相同。我们可以用下面的代码来创建I/O完成端口。

 

隐藏在之创建完成端口的秘密:

1. 创建一个完成端口

CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, dwNumberOfConcurrentThreads);

 

2. 设备列表,完成端口把它同一个或多个设备相关联。

CreateIoCompletionPort(hDevice, hCompPort, dwCompKey, 0) ;

 

第二步:

根据处理器个数,创建cpu*2个工作线程:

CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,0, &ThreadID))

与此同时,服务器调用WSASocket,bind, listen, WSAAccept,之后,调用

CreateIoCompletionPort((HANDLE) Accept, CompletionPort... )把一个套接字句柄和一个完成端口绑定到一起。完成端口又同一个或多个设备相关联着,所以以套接字为基础,投递发送和请求,对I/O处理。接着,可以依赖完成端口,接收有关I/O操作完成情况的通知。再看程序里:

WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,

 &(PerIoData->Overlapped), NULL)开始调用,这里象前面讲过的一样,既然是异步I/O,所以WSASend和WSARecv的调用会立即返回。

 

系统处理:

当一个设备的异步I/O请求完成之后,系统会检查该设备是否关联了一个完成端口,如果是,系统就向该完成端口的I/O完成队列中加入完成的I/O请求列。

 

然后我们需要从这个完成队列中,取出调用后的结果(需要通过一个Overlapped结构来接收调用的结果)。怎么知道这个队列中已经有处理后的结果呢,调用GetQueuedCompletionStatus函数。

 

工作线程与完成端口:

和异步过程调用不同(在一个Overlapped I/O完成之后,系统调用该回调函数。OS在有信号状态下(设备句柄),才会调用回调函数(可能有很多APCS等待处理了))

 

GetQueuedCompletionStatus

在工作线程内调用GetQueuedCompletionStatus函数。

GetQueuedCompletionStatus(

    HANDLE CompletionPort,

    LPDWORD lpNumberOfBytesTransferred,

    LPDWORD lpCompletionKey,

    LPOVERLAPPED *lpOverlapped,

    DWORD dwMilliseconds

);

CompletionPort:指出了线程要监视哪一个完成端口。很多服务应用程序只是使用一个I/O完成端口,所有的I/O请求完成以后的通知都将发给该端口。

lpNumberOfBytesTransferred:传输的数据字节数

lpCompletionKey:

完成端口的单句柄数据指针,这个指针将可以得到我们在CreateIoCompletionPort中申请那片内存。

lpOverlapped:

重叠I/O请求结构,这个结构同样是指向我们在重叠请求时所申请的内存块,同时和lpCompletionKey,一样我们也可以利用这个内存块来存储我们要保存的任意数据。

dwMilliseconds:

等待的最长时间(毫秒),如果超时,lpOverlapped被设为NULL,函数返回False.

 

GetQueuedCompletionStatus功能及隐藏的秘密:

GetQueuedCompletionStatus使调用线程挂起,直到指定的端口的I/O完成队列中出现了一项或直到超时。(I/0完成队列中出现了记录)调用GetQueuedCompletionStatus时,调用线程的ID(cpu*2个线程,每个ServerWorkerThread的线程ID)就被放入该等待线程队列中。

     等待线程队列很简单,只是保存了这些线程的ID。完成端口会按照后进先出的原则将一个线程队列的ID放入到释放线程列表中。

这样,I/O完成端口内核对象就知道哪些线程正在等待处理完成的I/O请求。当端口的I/O完成队列出现一项时,完成端口就唤醒(睡眠状态中变为可调度状态)等待线程队列中的一个线程。线程将得到完成I/O项中的信息:传输的字节数,完成键(单句柄数据结构)和Overlapped结构地址,线程是通过GetQueuedCompletionStatus返回这些信息,等待CPU的调度。

GetQueuedCompletionStatus返回可能有多种原因,如果传递无效完成端口句柄,函数返回False,GetLastError返回一个错误(ERROR_INVALID_HANDLE),如果超时,返回False, GetLastError返回WAIT_TIMEOUT, i/o完成队列删除一项,该表项是一个成功完成的I/O请求,则返回True。

 

    调用GetQueuedCompletionStatus的线程是后进先出的方式唤醒的,比如有4个线程等待,如果有一个I/O,最后一个调用GetQueuedCompletionStatus的线程被唤醒来处理。处理完之后,再调用GetQueuedCompletionStatus进入等待线程队列中。

 

深入分析完成端口线程池调度原理:

    假设我们运行在2CPU的机器上。创建完成端口时指定2个并发,创建了4个工作线程加入线程池中等待完成I/O请求,且完成端口队列(先入先出)中有3个完成I/O的请求的情况:

 工作线程运行, 创建了4个工作线程,调用GetQueuedCompletionStatus时,该调用线程就进入了睡眠状态,假设这个时候,I/O完成队列出现了三项,调用线程的ID就被放入该等待线程队列中, (如图):

 

等待的线程队列(后进先出)

 

进队列

 

出队列

 

 

线

程

A

 

 

线

程

B

 

 

线

程

C

 

 

线

程

D

I/O完成端口内核对象(第3个参数等级线程队列),因此知道哪些线程正在等待处理完成的I/O请求。当端口的I/O完成队列出现一项时,完成端口就唤醒(睡眠状态中变为可调度状态)等待线程队列中的一个线程(前面讲过等待线程队列是后进先出)。所以线程D将得到完成I/O项中的信息:传输的字节数,完成键(单句柄数据结构)和Overlapped结构地址,线程是通过GetQueuedCompletionStatus返回这些信息。

在前面我们指定了并发线程的数目是2,所以I/O完成端口唤醒2个线程,线程D和线程C,另两个继续休眠(线程B,线程A),直到线程D处理完了,发现表项里还有要处理的,就唤醒同一线程继续处理。

 

等待的线程队列(后进先出)

 

进队列

 

出队列

 

 

线

程

A

 

 

线

程

B

 

释放线程队列

 

 

线

程

C

 

 

线

程

D

 

线程并发量:

    并发量限制了与该完成端口相关联的可运行线程的数目, 它类似阀门的作用。 当与该完成端口相关联的可运行线程的总数目达到了该并发量,系统就会阻塞任何与该完成端口相关联的后续线程的执行, 直到与该完成端口相关联的可运行线程数目下降到小于该并发量为止。所以解释了线程池中的运行线程可能会比设置的并发线程多的原因。

    它的作用:

最有效的假想是发生在有完成包在队列中等待,而没有等待被满足,因为此时完成端口达到了其并发量的极限。此时,一个正在运行中的线程调用 GetQueuedCompletionStatus时,它就会立刻从队列中取走该完成包。这样就不存在着环境的切换,因为该处于运行中的线程就会连续不断地从队列中取走完成包,而其他的线程就不能运行了。

注意:如果池中的所有线程都在忙,客户请求就可能拒绝,所以要适当调整这个参数,获得最佳性能。

线程并发:D线程挂起,加入暂停线程,醒来后又加入释放线程队列。

 

线

程

C

 

 

线

程

B

 

 

线

程

A

 

出队列

 

进队列

 

等待的线程队列(后进先出)

 

释放线程队列

 

暂停线程

 

 

线

程

D

线程的安全退出:

PostQueudCompletionStatus函数,我们可以用它发送一个自定义的包含了OVERLAPPED成员变量的结构地址,里面包含一个状态变量,当状态变量为退出标志时,线程就执行清除动作然后退出。

 

完成端口使用需要注意的地方:

 1.在执行wsasend和wsarecv操作前,请先将overlapped结构体使用memset进行清零。

Overlapped模型深入分析(原理篇)   Overlapped I/O模型深入分析简述:     Overlapped I/O也称Asynchronous  I/O,异步I/O模型。异步I/O和同步I/O不同,同步I/O时,程序被挂起,一直到I/O处理完,程序才能获得控制。异步I/O,调用一个函数告诉OS,进行I/O操作,不等I/O结束就立即返回,继续程序执行,操作系统完成I/O之后,通知消息给你。Overlapped I 阅读详情

相关推荐

嘉立创EDA 2.4 + Astra:自然语言驱动PCB设计的工程落地实践

PCB设计正从手动绘图迈向语义驱动的新范式。所谓‘自然语言生成PCB’,本质是将工程师的设计意图(如器件选型、阻抗控制、DRC规则)通过深度语义理解转化为EDA可执行指令,其技术核心在于跨域知识映射——融合IPC-2221标准、嘉立创工艺约束与芯片Datasheet语义。这种能力显著提升硬件开发效率,尤其在电源管理、蓝牙射频、CAN总线等结构化场景中,实现原理图→PCB→Gerber全流程闭环。它并非替代工程师,而是将重复性建模与规则翻译工作自动化,使设计重心回归电路原理与系统级决策。本文聚焦嘉立创EDA

chubaisheng8627的博客 412

Overlapped I/O模型深入分析

 (转)简述:     Overlapped I/O也称Asynchronous  I/O,异步I/O模型。异步I/O和同步I/O不同,同步I/O时,程序被挂起,一直到I/O处理完,程序才能获得控制。异步I/O,调用一个函数告诉OS,进行I/O操作,不等I/O结束就立即返回,继续程序执行,操作系统完成I/O之后,通知消息给你。Overlapped I/O只是一种模型,它可以由内核对象(

hyuantian的专栏 1006

windows 下 IOCP(I/O Completion Port,I/O完成端口)

IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求。这样就有很多的线程并行地运行在系统中。而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上。再加上创建新线程的开销

h a 6 6 6 c k 为 你解决复杂难题! 1504

封包和拆包

   对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就是封包和拆包.自从我从事网络通讯编程工作以来(大概有三年的时间了),我一直在思索和改进封包和拆包的方法.下面就针对这个问题谈谈我的想法,抛砖引玉.若有不对,不妥之处,恳求大家指正.在此先谢过大家了.一.为什么基于TCP的通讯程序需要进行封包和拆包.TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是

fengge_ylf的专栏 1万+

从数据到特征:基于CAT12的MRI图像预处理实战指南

本文详细介绍了使用CAT12工具进行MRI图像预处理的完整实战流程。从数据获取、环境搭建到核心的AC-PC校正、组织分割、空间标准化与调制,逐步解析如何将原始脑影像数据转化为可用于机器学习的标准化特征图。重点阐述了预处理作为脑影像分析‘生命线’的重要性,并提供了避坑指南与自动化脚本建议,帮助研究者构建高质量的阿尔茨海默症分类模型输入特征。

weixin_29065959的博客 310

基于OFDM的实时图像传输系统MATLAB仿真:MPSK与MQAM调制性能对比与误码率分析

本文详细介绍了基于OFDM的实时图像传输系统在MATLAB中的仿真实现,重点对比了MPSK与MQAM调制方式的性能差异与误码率分析。通过搭建OFDM系统模型,探讨了QPSK和16QAM在不同信道条件下的表现,包括频谱效率、抗噪能力和误码率等关键指标。文章还提供了MATLAB代码示例和实用技巧,帮助读者快速掌握OFDM图像传输系统的核心算法与优化方法。

weixin_29064009的博客 355

网络-WinSocket-I/O模型

WinSocket下编程,总共有7种套接字I/O模型可供选择,分别是阻塞(block)、非阻塞(nonblock)、选择(I/O复用)(select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped )以及完成端口(CompletionPort)模型。 其中,默认情况下使用WinSocket进行编程,都属于阻塞模型,详细编程过

我了个去 1136

Power Bi数据分析案例:在线零售平台销售数据分析

该数据集为,涵盖2023年1月至2024年3月,包含用户群体特征、购买行为、产品偏好以及参与度指标。用户维度:Customer_ID,Age,Gender,City产品维度:Product_Category,Unit_Price事实表:Order_ID,Quantity,Total_Amount,Discount_Amount,Rating,Delivery_Time在Power Query当中处理销售日期列,并新增年龄段、浏览页面分段列。

2301_79586168的博客 1279

完成端口(I/O completion)原理

完成端口(I/O completion)原理收藏   异步过程调用(apcs)问题: 只有发overlapped请求的线程才可以提供callback函数(需要一个特定的线程为一个特定的I/O请求服务)。 完成端口(I/O completion)的优点: 不会限制handle个数,可处理成千上万个连接。I/O completion port允许一个线程将一个请求暂时

chenchenlin0811的博客 1558

allegro如何设置走线等长

设置走线等长!

weixin_42499230的博客 6937

YOLOv8改进 | 主干网络 | 在backbone添加Swin-Transformer层【论文必备】

YOLOv8改进,Swin-Transform,YOLOv8添加Swin-Transform

kay_545 2367

I/O Completion Ports-I/O完成端口

I/O Completion Ports I/O completion ports are the mechanism by which an application uses a pool of threads that was created when the application was started to process asynchronous I/O requests. The

尘雨::执着VC 2598

Coze实战:解锁多Bot协同与条件分支工作流的奥秘

本文详细介绍了在字节跳动Coze平台实现多Bot协同与条件分支工作流的方法。首先阐述了Coze平台的功能优势,包括丰富的插件、知识库和工作流功能。随后分步骤讲解了多Bot协同的实现:从准备工作、创建Bot到协同配置,并提供了电商客服的实例演示。在条件分支工作流部分,详细说明了条件节点的作用类型、条件设定方法以及具体配置操作,强调测试优化的重要性。最后通过电商平台综合案例,展示了多Bot协同与条件分支的实际应用效果,并针对常见问题提供解决方案。文章为开发者在Coze平台上构建智能应用提供了实用指导,有助于提升

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 450

Windows 的 IOCP(I/O Completion Ports,完成端口)

IOCP 是 Windows 平台上最高性能的 I/O 模型。它通过“完成通知”机制,将繁重的 I/O 工作完全交由内核处理,应用程序线程只需专注于业务逻辑,从而实现了在高并发压力下依然能保持低延迟和高吞吐量。虽然其编程模型比select或epoll更复杂,需要精心设计内存管理和上下文结构,但对于追求极致性能的服务器端程序来说,它是无可替代的选择。

2401_83957781的博客 972

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

我好像病了的博客 2449

把事务数据变成可分析数据:用 ABAP CDS 构建 Cube View 与 Query View,并拆解 OData 取数的底层路径

ABAP CDS分析建模:Cube与Query视图的实践解析 本文探讨了ABAP CDS分析建模中Cube View与Query View的核心区别与应用场景: 架构定位 Cube View作为分析型数据源,定义维度和度量的基础语义 Query View作为消费投影,控制查询可见字段和聚合逻辑 关键实现 通过@Analytics.dataCategory: #CUBE声明分析数据源 使用@DefaultAggregation确保指标口径一致性 @Analytics.query: true启用分析引擎特性 运

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 141

理解I/O Completion Port(完成端口)

欢迎阅读此篇IOCP教程。我将先给出IOCP的定义然后给出它的实现方法,最后剖析一个Echo程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼。OK,但我不能保证你明白IOCP的一切,但我会尽我最大的努力。以下是我会在这篇文章中提到的相关技术:  I/O端口  同步/异步  堵塞/非堵塞  服务端/客户端  多线程程序设计  Winsock API 2.0  在这之前,我曾经开发过一个项目,

Johnny的专栏 1328

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: 利用VS2005进行dump文件调试
下一篇: 设计及编码质量改进之降低耦合度
UU_Yang
博客等级 码龄23年 926粉丝 213原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值