I/O完成端口 - CreateIoCompletionPort函数

函数原型:

HANDLE WINAPI CreateIoCompletionPort(
  _In_     HANDLE    FileHandle,
  _In_opt_ HANDLE    ExistingCompletionPort,
  _In_     ULONG_PTR CompletionKey,
  _In_     DWORD     NumberOfConcurrentThreads
);

功能:

1、创建一个输入/输出完成端口(I/O完成端口,I/O Completion Port),并将一个特定的文件句柄和它关联起来。或者创建一个不与文件句柄相关联的I/O完成端口,可以在后面需要的时候再关联文件句柄。

2、将一个一经打开的文件句柄实例和一个I/O完成端口关联起来。这样一来,当在这个文件句柄上的异步I/O操作完成时,进程就会收到通知(notification)。

注:术语文件句柄(File Handle)在这里表示的是一种系统抽象概念,代表一切可重叠的I/O端点,不仅仅是磁盘上的文件。任何支持重叠I/O的系统对象,比如网络端口、TCP套接字、命名管道、邮件槽等都可以被用作文件句柄。

参数详解:

FileHandle:

一个打开的文件句柄或者是 INVALID_HANDLE_VALUE

这个句柄必须是支持重叠I/O的对象。并且这个句柄必须是按重叠I/O完成的方式打开的。比如在调用 CreateFile 函数时必须指定 FILE_FLAG_OVERLAPPED 标志。

如果FileHandle的值是INVALID_HANDLE_VALUE 那么函数会创建一个不与文件句柄关联的I/O完成端口。此时ExistingCompletionPort参数必须是NULLCompletionKey将被忽略。

ExistingCompletionPort:

指向现有的I/O完成端口的句柄或者是NULL

如果参数指定的是I/O完成端口,函数会将它和 FileHandle 相关联。函数成功时返回现有的I/O完成端口,不会创建新的I/O完成端口。

如果参数是 NULL ,函数会创建一个新的I/O完成端口。此时,如果FileHandle的值是有效的,就会把它和这个端口相关联。否则不会发生任何关联。函数成功时返回一个新的I/O完成端口。

CompletionKey:

每个句柄用户定义的完成键,会被包含在每一个I/O完成数据包里面。

NumberOfConcurrentThreads:

操作系统可以允许的同时处理I/O完成端口的I/O完成数据包的最大线程数。当ExistingCompletionPort不为空时这个参数将被忽略。

如果此参数为零,则系统允许与系统中的处理器一样多的并发运行线程。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IOCP全称I/O Completion Port,中文译为I/O完成端口IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。 大体上来讲,使用完成端口只用遵循如下几个步骤: (1) 调用 CreateIoCompletionPort() 函数创建一个完成端口,而且在一般情况下,我们需要且只需要建立这一个完成端口,把它的句柄保存好,我们今后会经常用到它…… (2) 根据系统中有多少个处理器,就建立多少个工作者(为了醒目起见,下面直接说Worker)线程,这几个线程是专门用来和客户端进行通信的,目前暂时没什么工作; (3) 下面就是接收连入的Socket连接了,这里有两种实现方式:一是和别的编程模型一样,还需要启动一个独立的线程,专门用来accept客户端的连接请求;二是用性能更高更好的异步AcceptEx()请求。 (4) 每当有客户端连入的时候,我们就还是得调用CreateIoCompletionPort()函数,这里却不是新建立完成端口了,而是把新连入的Socket(也就是前面所谓的设备句柄),与目前的完成端口绑定在一起。 至此,我们其实就已经完成完成端口的相关部署工作了,嗯,是的,完事了,后面的代码里我们就可以充分享受完成端口带给我们的巨大优势,坐享其成了,是不是很简单呢? (5) 例如,客户端连入之后,我们可以在这个Socket上提交一个网络请求,例如WSARecv(),然后系统就会帮咱们乖乖的去执行接收数据的操作,我们大可以放心的去干别的事情了; (6) 而此时,我们预先准备的那几个Worker线程就不能闲着了, 我们在前面建立的几个Worker就要忙活起来了,都需要分别调用GetQueuedCompletionStatus() 函数在扫描完成端口的队列里是否有网络通信的请求存在(例如读取数据,发送数据等),一旦有的话,就将这个请求从完成端口的队列中取回来,继续执行本线程中后面的处理代码,处理完毕之后,我们再继续投递下一个网络通信的请求就OK了,如此循环。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值