Windows核心编程 - 异步I/O之完成端口

1. 背景

    构建一个服务应用程序,常用的主要有两种模型: 串行模型和并行模型。

    1)串行模型: 一个线程等待一个请求,当请求到达时,线程被唤醒对请求进行处理;处理完后再接着等待下一个请求。

           缺点:不能同时处理多个请求。

     2)并行模型:一个线程等待一个请求,当请求到达时,线程会创建一个新的线程来处理请求。然后线程进入下一次循环等待下一个请求。新的线程处理完请求后,会自行终止。

          缺点:如果请求数量较多,需要创建相对数量的线程,一方面线程频繁地创建、终止会带来开销;另一方面,线程数量过多,但实际上机器的CPU数量有限,且这些线程大多都是处于可调度的状态,那么内核需花费很多在线程的切换上下文的过程,导致没有多少CPU时间来执行真正需要的任务。 I/O完成端口内核对象可解决此类问题。

 

2. 创建I/O完成端口

        I/O完成端口会对并发运行的线程数量设定一个上限,即线程数量不能随着请求个数增加而线性增长,一般是根据机器本身的CPU个数来选择一个合适的上限,以减少内核执行线程上下文切换的花销。在应用程序初始化的时候,会创建一个线程池,并让线程池中的线程在应用程序运行期间处于可调用度状态,得以提高服务应用程序的性能。

        创建I/O完成端口的函数用: CreateIoCompletionPort(),此函数有参数可指定线程池的大小。当创建一个I/O完成端口时,系统内核会创建5个不同的数据结构:

      1)设备列表:表示与该端口相关联的一个或多个设备;

      2)I/O完成队列(先入先出):当设备的一个异步I/O请求完成时,设备会检查该设备是否与一个I/O完成端口相关联,如果是则将该已完成的I/O请求追加到I/O完成队列;

      3)等待线程队列(后入先出):当线程池中的每个线程调用GetQueueCompletionStatus()时,调用线程的线程ID会被添加到等待线程队列,这是告知I/O完成端口内核对象,有哪些线程在等待处理已完成的I/O请求,当I/O完成队列中出现一项时,I/O完成端口就会唤醒等待线程队列中的一个线程来进行处理。该队列是后入先出的,假设有3个线程在等待线程队列中,当I/O完成队列出现一个项时,则最后调用GetQueueCompletionStatus()的线程3会被唤醒来处理这个项。线程3处理完这个项后,会再次调用GetQueueCompletionStatus()进入等待线程队列,这时如果I/O完成队列又来了一项,则线程3会被再次唤醒来处理这个项。

      4)已释放线程列表:当完成端口在等待线程队列中唤醒的线程或已暂停的线程被唤醒,都会进入到已释放线程列表;

      5)已暂停线程列表:如果一个已释放的线程,在工作过程中切换到了等待状态,则会被放入到已暂停线程列表。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值