windows下异步IO

所谓异步IO,就是当线程向设备驱动程序发送一个IO请求后,线程不会等待处理,而是继续执行,设备驱动程序去完成实际的IO操作,再通过其他方式通知程序

注意:

如果我们发送一个异步IO请求给设备驱动程序,设备驱动程序不一定会以异步处理IO请求,有时候会选择以同步的方式来请求。当我们IO请求发送后,操作系统检查我们的数据是否在系统的缓存中,如果在缓存中,那么操作系统不会把这个请求发送给设备驱动程序,而会直接将数据从高速缓存中复制给我们的程序,直接完成IO请求

 

如果IO操作是以同步方式执行的,那么ReadFile和WriteFile将会返回非0值,如果是以异步的,或者发生了错误,那么将会返回FALSE

1.OVERLAPPED

OVERLAPPED即重叠的,也就是说一个线程可以在读的时候做其他的事情,具体我在之前有写过这个

http://www.cnblogs.com/linyilong3/archive/2012/05/03/2480451.html

之前一直不知道的一点是Offset和OffsetHight,一直都是设置为0,然后缓冲区开到最大,今天看windows核心编程发现这两个数字组成了一个64位的数字,假设我们把Offset设置为10,OffsetHight设置为0,那么在读取数据的时候将会从10开始读取

 

OVERLAPPED IO操作每次都需要指定操作的位置,在同步IO中,我们在进行完一个IO后,文件的都会移动偏移指针,下次我们再次对文件进行IO操作的时候,文件将会从上一次操作结束的地方开始,但是在异步IO中,我们如果发起两个IO操作,可能是第二个IO操作先执行并且完成,这个时候第二个IO请求可能从起始位置开始,第一个则从第二个IO请求结束的位置开始操作,这个时候就会造成混乱

 

等待IO完成通知:

1.WaitForSingleObject,触发设备内核对象

 

2.可以利用OVERLAPPED里面的hEvent,这在windows核心编程里面的示例主要是在有多个IO请求的时候,比如一个读一个些,WaitForSingleObject无法知道究竟是哪个完成,可以为每个事件创建单独的hEvent

 

2.可提醒IO


windows核心编程上是说可提醒IO非常糟糕,应该避免使用,他是使用ReadFileEx或者WriteFileEx,这两个函数比原来的函数多了一个参数,是一个函数指针,这个函数是当IO请求完成后需要回调的函数,但是这些回调函数并不回立即调用,而是要等到线程将自己设置为可提醒状态,这6个函数:SleepEx,WaitForSingleObjectEx,WaitforMultipleObjectsEx,SignalObjectAndWait,GetQueuedCompletionStatusEx,MsgWaitForMultipleObjectsEx,当线程进入可提醒状态的时候,并且IO请求队列已经有完成的了,操作系统将会开始调用这些回调函数,直到完成队列里面的没有消息了,那么我们对 可提醒调用的函数将会返回,我们可以利用这个特性,来让暂停执行的线程继续往下执行

 

劣势:

必须有一个回调函数,增加代码复杂度,因为这些回调函数没有足够的与某个问题有关的上下文信息,所以一些信息只能放到全局变量中(原本我想可以利用C++的类解决这个问题,但是后来想了下,如果局部变量要变成类成员变量,那么会增加类的复杂度)

 

线程,发出IO请求的线程同时对完成通知作出处理,如果一个线程发出多个请求,就必须处理多个请求,负载不均衡,程序的伸缩性不太好

 

完成端口:

所谓完成端口,就是由用户创建一个端口,并且将设备的HANDLE与这个端口关联,这样当IO完成后,将会通知这个端口,再由这个端口进行处理

 

而完成端口则会根据用户指定的线程数来创建线程,一般是CPU*2的数量,因为创建过多那么将会把大部分时间都花在线程上下文切换上面

 

完成端口总共保存四个列表,一个是IO完成队列,一个是等待线程队列,一个是释放线程列表还有已暂停线程的列表,暂停线程列表和等待线程队列的不同是暂停线程列表是利用函数把线程挂起,如果用户唤醒了这个线程那么这个线程将会被加入释放列表,而等待线程队列是用户调用GetQueuedCompletionStatus来等待IO消息,用户也可以通过PostQueuedCompletionStatus来将线程加入IO完成队列

 

如果不需要将IO请求添加到IO完成端口的队列,可以Overlapped.hEvent = (HANDLE)((DWORD_PTR)Overlapped.hEvent | 1)

posted @ 2012-12-26 19:22  linyilong  阅读(3595)  评论(0编辑  收藏  举报