关于IOCP的理解

IOCP出现的原因:

 

windows系统的设计目标就是设计一个出色的,安全健壮的系统。为各种程序提供服务,这时候就出现了两种模型:

1)串行模型:一个线程等待一个客户发出的请求,当请求到来的时候,线程唤醒然后对请求处理。

2)并行模型:一个线程等待一个客户发生的请求,当请求到来的时候,创建新的线程去对请求处理,而原先的线程就会再次陷入等待状态。

 

串行模型的问题是不能同时处理多个请求。如果发生多个请求时,一次只能处理一个请求,效率很低。不过ping服务器就时这种模型。

并行模型为了突破串行模型的问题,创建多个处理请求的线程,能够很容易的体现出多处理器的优势。

并行模型的问题是在同时处理多个客户发来的请求时,系统中会存在很多并行执行状态的线程,由于线程的上下背景文切换会导致浪费大量的cpu时间,以至于分给各个线程的cpu时间就会很少,效率也会变低,但是为了解决这一问题,微软提出了IOCP内核对象。

 

IOCP出现的原因:为了解决并发模型切换上下背景文浪费太多时间的情况。背后的理论是:限制并发运行的线程的最大数量。一般是cpu数量*2(cpu数量通过GetSystemInfo获取)

《Windows核心编程》中提出IOCP内核对象是最最麻烦的内核对象,windows中利用CreateIOCompletionPort函数来创建IO完成端口时,系统创建了5个相关的数据结构:设备列表、IO完成队列(先进先出)、等待线程队列(后进先出)、已释放线程列表、已暂停线程列表。

 

 添加删除
设备列表CreateIOCompletionPort被调用clsoehandle释放IOCP句柄
IO完成队列1)IO请求完成、2)PostQueuedCompletionStatus被调用在等待线程队列的线程唤醒,并取出一个IO请求
等待线程队列GetPostCompletionStatus被调用在IO完成队列非空,且运行的线程小于并发线程限制数量时,线程从GetPostCompletionStatus处返回执行。IO完成队列会删除取出的项,该线程加入已释放线程队列
已释放线程列表1)等待队列中的线程被唤醒  2)暂停的线程被唤醒1)线程再次调用GetPostCompletionStatus,从已释放线程队列移除,加入等待线程队列  2)线程挂起,加入已暂停线程列表中
已暂停线程列表线程将自己挂起挂机线程被唤醒,移除已暂停的线程列表,加入已释放线程列表

 

 

 

 

 

整个过程相当于

1.创建IO完成端口 

  HANDLE WINAPI CreateIoCompletionPort(
    __in      HANDLE FileHandle,               //文件 设备句柄
    __in_opt  HANDLE ExistingCompletionPort,   //与设备关联的IO完成端口句柄,为NULL时,系统会创建新的完成端口
    __in      ULONG_PTR CompletionKey,         //完成键,用它来区分各个设备。
    __in      DWORD NumberOfConcurrentThreads  //允许运行的最大线程数量,如果传0表示允许并发执行的线程数量等于CPU主机数量(我的本机是4核8线程,计算机将CPU主机数量当作了8)
  );

  

  这个函数会完成两个任务: 一是创建一个IO完成端口对象,二是将一个设备与一个IO完成端口关联起来。

  

  2.将已完成的IO请求投递到IO完成端口的队列   

  PostQueuedCompletionStatus(
    _In_ HANDLE CompletionPort,                             //完成端口的句柄
    _In_ DWORD dwNumberOfBytesTransferred,      
    _In_ ULONG_PTR dwCompletionKey,
    _In_opt_ LPOVERLAPPED lpOverlapped
  );

  

  后三个参数是为调用了那个GetQueuedCompletionStatus的线程而准备的。

 

  3.GetQueuedCompletionStatus函数在检查IO完成队列里是否有已经完成的IO请求。  

  BOOL
  WINAPI
  GetQueuedCompletionStatus(
    _In_ HANDLE CompletionPort,                                     //完成端口句柄
    _Out_ LPDWORD lpNumberOfBytesTransferred,
    _Out_ PULONG_PTR lpCompletionKey,
    _Out_ LPOVERLAPPED * lpOverlapped,
    _In_ DWORD dwMilliseconds                                      //等待时间
  );

 

  (1)在等待线程队列中的线程调用GetQueuedCompletionStatus检查IO完成队列里是否有已经完成的IO请求时,如果IO完成队列中存在已完成的IO请求,则GetQueuedCompletionStatus先删除IO完成队列中这个对应的项,然后将线程ID转移到已释放线程列表中(即当前线程属于已释放列表中的一员了)

  (2)在已释放列表中的线程调用GetQueuedCompletionStatus检查IO完成队列里是否有已经完成的IO请求时,如果IO完成队列中不再存在已完成的IO请求,则线程ID再次回到等待线程队列中中。(即当前线程属于等待线程队列中的一员了)

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值