转自:http://blog.sina.com.cn/s/blog_c2ef450f010192hx.html
APC 异步过程调用
记得第一次看见这个名词的时候,觉得云里雾罩,然而上网看了下它的介绍,感觉说的都是没头没脑的
然而今天,我再次接触了它,我将自己对其的理解写下,若有不对,欢迎指正(参照《windows核心编程 》第五版)
好啦,废话少说,让我们进入正题:
首先我们应该明白的是在创建线程的时候,这个所谓的APC就已经建立,并且与线程相关联,并且这个APC是个队列;
队列中项的产生:
那么是谁往队列里面添加内容呢,这个就要说到设备驱动程序了,现在是不是感觉不知所以然,听我慢慢讲来; 当一个线程发出一个I/O请求时(在这里我们讲的是异步I/O请求哦),设备驱动程序接收它的请求,那么线程呢就执行自己剩下的工作(直到某一点,它实在是执行不去(因为在这点必须要得到请求的I/O结果)),那么设备驱动程序在执行完I/O请求后,他怎么让线程直到他已经执行完I/O了呢?
那就是它会在APC队列中添加一项,那么问题又来啦,它又怎么会知道往这个线程中的APC队列中添加项呢,嘿嘿,这当然是线程告诉他的,在哪告诉的呢,当然是在发送I/O请求时告诉的,在这我也不卖官司啦,直接说啦,线程在请求I/O操作时用的是ReadFileEx()或者WriteFileEx()函数,这两个函数在发送I/O请求的时候,就告诉设备驱动程序,说”嗨,哥们,你处理完我的请求后,就把通知发送到我的APC队列中啊,哥等你”; (当然这个队列项的内容就是那个完成函数的地址和在I/O请求时那个OVERLAPPED结构的地址(至于什么是完成函数和OVERLAPPED结构,我想就不用多说了把)),
这下我们知道了APC队列中项的由来,那么接下来我们要了解的是项的处理:
在项添加到APC队列中时,它不会被马上处理,(线程在有其他任务处理的情况下不能被打断为了对线程APC队列中的项进行处理,线程必须将自己置为可提醒状态)
那么什么是可提醒状态,怎么才能设为可提醒状态呢?
可提醒状态在我感觉他就是为了处理APC中的项而出来的概念,因为在队列中有项的情况下,线程会处理那些项,而当APC队列中没有项的时候,那么线程就会是挂起状态;(在我看来,这里的可提醒应该是通知的意思,就是通知APC队列中有项,让它处理)
至于怎么让线程成为可提醒状态,windows为我们提供了6个函数
SleepEx()
WaitForSingleObjectEx()
WaitForMultiObjectEx()
SignalObjectAndWait()
GetQueuedCOmpletionStatu
MsgWaitForMultipleObject
前五个函数的参数中最后一个参数是个BOOl值,表示调用线程是不是应该将自己置为可提醒状态
对于最后一个函数的最后一个参数我们应该使用MWMO_ALERTABLE标志来让线程进入可提醒状态
还有一点是,当线程在挂起状态时,将其唤醒的方法可以是等待内核对象的触发,或者也可以在APC队列中出现一个项,当一个项出现的情况下,系统会唤醒我们的线程(通过回调函数)并清空队列,然后函数会立即返回---线程不会再次进行睡眠状态来等待内核对象被触发