APC异步过程调用
轉(zhuǎn)自:http://blog.sina.com.cn/s/blog_c2ef450f010192hx.html
APC?異步過(guò)程調(diào)用
?
記得第一次看見(jiàn)這個(gè)名詞的時(shí)候,覺(jué)得云里霧罩,然而上網(wǎng)看了下它的介紹,感覺(jué)說(shuō)的都是沒(méi)頭沒(méi)腦的
然而今天,我再次接觸了它,我將自己對(duì)其的理解寫(xiě)下,若有不對(duì),歡迎指正(參照《windows核心編程?》第五版)????????????????狼影?--------- 2013、10、18
好啦,廢話少說(shuō),讓我們進(jìn)入正題:
?
首先我們應(yīng)該明白的是在創(chuàng)建線程的時(shí)候,這個(gè)所謂的APC就已經(jīng)建立,并且與線程相關(guān)聯(lián),并且這個(gè)APC是個(gè)隊(duì)列;
隊(duì)列中項(xiàng)的產(chǎn)生:
那么是誰(shuí)往隊(duì)列里面添加內(nèi)容呢,這個(gè)就要說(shuō)到設(shè)備驅(qū)動(dòng)程序了,現(xiàn)在是不是感覺(jué)不知所以然,聽(tīng)我慢慢講來(lái);?當(dāng)一個(gè)線程發(fā)出一個(gè)I/O請(qǐng)求時(shí)(在這里我們講的是異步I/O請(qǐng)求哦),設(shè)備驅(qū)動(dòng)程序接收它的請(qǐng)求,那么線程呢就執(zhí)行自己剩下的工作(直到某一點(diǎn),它實(shí)在是執(zhí)行不去(因?yàn)樵谶@點(diǎn)必須要得到請(qǐng)求的I/O結(jié)果)),那么設(shè)備驅(qū)動(dòng)程序在執(zhí)行完I/O請(qǐng)求后,他怎么讓線程直到他已經(jīng)執(zhí)行完I/O了呢?
那就是它會(huì)在APC隊(duì)列中添加一項(xiàng),那么問(wèn)題又來(lái)啦,它又怎么會(huì)知道往這個(gè)線程中的APC隊(duì)列中添加項(xiàng)呢,嘿嘿,這當(dāng)然是線程告訴他的,在哪告訴的呢,當(dāng)然是在發(fā)送I/O請(qǐng)求時(shí)告訴的,在這我也不賣官司啦,直接說(shuō)啦,線程在請(qǐng)求I/O操作時(shí)用的是ReadFileEx()或者WriteFileEx()函數(shù),這兩個(gè)函數(shù)在發(fā)送I/O請(qǐng)求的時(shí)候,就告訴設(shè)備驅(qū)動(dòng)程序,說(shuō)”嗨,哥們,你處理完我的請(qǐng)求后,就把通知發(fā)送到我的APC隊(duì)列中啊,哥等你”; (當(dāng)然這個(gè)隊(duì)列項(xiàng)的內(nèi)容就是那個(gè)完成函數(shù)的地址和在I/O請(qǐng)求時(shí)那個(gè)OVERLAPPED結(jié)構(gòu)的地址(至于什么是完成函數(shù)和OVERLAPPED結(jié)構(gòu),我想就不用多說(shuō)了把)),
這下我們知道了APC隊(duì)列中項(xiàng)的由來(lái),那么接下來(lái)我們要了解的是項(xiàng)的處理:
在項(xiàng)添加到APC隊(duì)列中時(shí),它不會(huì)被馬上處理,(線程在有其他任務(wù)處理的情況下不能被打斷為了對(duì)線程APC隊(duì)列中的項(xiàng)進(jìn)行處理,線程必須將自己置為可提醒狀態(tài))
那么什么是可提醒狀態(tài),怎么才能設(shè)為可提醒狀態(tài)呢?
可提醒狀態(tài)在我感覺(jué)他就是為了處理APC中的項(xiàng)而出來(lái)的概念,因?yàn)樵陉?duì)列中有項(xiàng)的情況下,線程會(huì)處理那些項(xiàng),而當(dāng)APC隊(duì)列中沒(méi)有項(xiàng)的時(shí)候,那么線程就會(huì)是掛起狀態(tài);(在我看來(lái),這里的可提醒應(yīng)該是通知的意思,就是通知APC隊(duì)列中有項(xiàng),讓它處理)??記住!當(dāng)且僅當(dāng)線程的APC隊(duì)列中一項(xiàng)都沒(méi)有的情況下線程才會(huì)掛起
至于怎么讓線程成為可提醒狀態(tài),windows為我們提供了6個(gè)函數(shù)
SleepEx()
WaitForSingleObjectEx()
WaitForMultiObjectEx()
SignalObjectAndWait()
GetQueuedCOmpletionStatusEx()
MsgWaitForMultipleObjectEx()
前五個(gè)函數(shù)的參數(shù)中最后一個(gè)參數(shù)是個(gè)BOOl值,表示調(diào)用線程是不是應(yīng)該將自己置為可提醒狀態(tài)
對(duì)于最后一個(gè)函數(shù)的最后一個(gè)參數(shù)我們應(yīng)該使用MWMO_ALERTABLE標(biāo)志來(lái)讓線程進(jìn)入可提醒狀態(tài)
?
還有一點(diǎn)是,當(dāng)線程在掛起狀態(tài)時(shí),將其喚醒的方法可以是等待內(nèi)核對(duì)象的觸發(fā),或者也可以在APC隊(duì)列中出現(xiàn)一個(gè)項(xiàng),當(dāng)一個(gè)項(xiàng)出現(xiàn)的情況下,系統(tǒng)會(huì)喚醒我們的線程(通過(guò)回調(diào)函數(shù))并清空隊(duì)列,然后函數(shù)會(huì)立即返回---線程不會(huì)再次進(jìn)行睡眠狀態(tài)來(lái)等待內(nèi)核對(duì)象被觸發(fā)
總結(jié)
- 上一篇: 操作系统内核
- 下一篇: Kafka 优化参数 unclean.