西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)VC|VC++ → I/O完成端口的實現(xiàn)-Windows編程技巧

I/O完成端口的實現(xiàn)-Windows編程技巧

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:本站整理時間:2010/10/22 12:21:40字體大。A-A+

作者:佚名點擊:706次評論:0次標(biāo)簽: Windows 編程 完成端口

  • 類型:文字輸入大小:8KB語言:中文 評分:5.0
  • 標(biāo)簽:
立即下載
3 頁 完成端口內(nèi)部機制

完成端口內(nèi)部機制
當(dāng)傳遞NULL值給ExistingCompletionPort參數(shù)來調(diào)用CreateIoCompletionPort來創(chuàng)建完成端口時,將調(diào)用同名的NtCreateIoCompletion系統(tǒng)服務(wù)。實質(zhì)上,IoCompletion對象是建立在一個稱為隊列的內(nèi)核同步對象基礎(chǔ)上。系統(tǒng)創(chuàng)建一個完成端口的同時,在完成端口所分配到的內(nèi)存中初始化一個隊列對象(指向完成端口的指針同時指向了此隊列對象,因為隊列對象位于完成端口對象內(nèi)存的開始處)。當(dāng)一個線程調(diào)用CreateIoCompletionPort來創(chuàng)建完成端口時,第四個參數(shù)NumberOfConcurrentThreads即為隊列的并發(fā)值。NtCreateIoCompletion函數(shù)將調(diào)用KeInitializeQueue系統(tǒng)服務(wù)來初始化該端口的消息隊列。

當(dāng)應(yīng)用程序再次調(diào)用CreateIoCompletionPort時,將調(diào)用NtSetInformationFile服務(wù)來使參數(shù)一(文件句柄)與參數(shù)二(一個已有的完成端口)關(guān)聯(lián)起來。完成通知包FileCompletionInformation包含的信息:CreateIoCompletionPort的參數(shù)二ExistingCompletionPort(已有的完成端口句柄)和參數(shù)三CompletionKey(完成鍵)。NtSetInformationFile通過解引用操作從該文件句柄獲得對應(yīng)的文件對象,并且申請一個記錄完成上下文的數(shù)據(jù)結(jié)構(gòu)。這個數(shù)據(jù)結(jié)構(gòu)在NTDDK.H定義如下:

typedef struct _IO_COMPLETION_CONTEXT {
  PVOID Port;
  ULONG Key;
} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;

最后,將調(diào)用NtSetInformationFile系統(tǒng)服務(wù)設(shè)置文件對象中CompletionContext域的值。當(dāng)一個異步I/O在一個文件對象上完成時,系統(tǒng)內(nèi)部執(zhí)行具有I/O管理功能的IopCompleteRequest系統(tǒng)服務(wù),檢查文件對象中的CompletionContext域是否為非NULL。如果是,則I/O管理器生成一個完成通知包,通過調(diào)用KeInsertQueue系統(tǒng)服務(wù)將完成通知包投遞到完成端口隊列(注意,完成端口對象和隊列對象是同義的)。

當(dāng)一個服務(wù)器線程調(diào)用GetQueuedCompletionStatus時,它將調(diào)用NtRemoveIoCompletion系統(tǒng)服務(wù)。在驗證參數(shù)后,并且將完成端口句柄轉(zhuǎn)換成一個指向該端口的指針后,NtRemoveIoCompletion調(diào)用KeRemoveQueue。

正如你所看到的,KeRemoveQueue和KeInsertQueue是完成端口模型的兩個引擎級函數(shù),它們決定阻塞在完成端口上等待I/O完成通知包的線程什么時候被喚醒。在系統(tǒng)內(nèi)部,隊列對象維護了完成端口上當(dāng)前活動線程的計數(shù)值,以及最大的并發(fā)活動線程的數(shù)量。當(dāng)一個線程調(diào)用KeRemoveQueue并且當(dāng)前活動線程數(shù)大于或等于并發(fā)數(shù)上限時,那么該線程將被投放到一個阻塞線程隊列(按LIFO順序)中,等待系統(tǒng)調(diào)度來獲取并處理完成通知包。此線程列表掛在隊列對象的外面,線程的控制塊數(shù)據(jù)結(jié)構(gòu)中有一個指針引用了一個與之相關(guān)的隊列對象;如果這個指針為NULL,則該線程沒有與隊列關(guān)聯(lián)。

Windows依賴與線程控制塊中的隊列指針來跟蹤和記錄那些“由于被阻塞在除了完成端口之外的其他事情上而變成不活動”的線程。那些有可能會導(dǎo)致一個線程阻塞的調(diào)度例程(例如KeWaitForSingleObject,KeDelayExecutionThread等等)要檢查該線程的隊列指針。如果該指針不為NULL,則這些函數(shù)調(diào)用KiActivateWaiterQueue—一個與隊列相關(guān)的函數(shù),它會遞減與該隊列相關(guān)聯(lián)的活動線程的計數(shù)值。如果計數(shù)值遞減到小于設(shè)置的并發(fā)值,并且此時至少有一個完成通知包在該隊列中,那么處于該隊列的線程列表最前面的那個線程被喚醒,并且把最老的(the oldest)完成通知包交給它處理。相反,無論何時,與一個隊列相關(guān)聯(lián)的線程在阻塞之后被喚醒時,調(diào)度程序執(zhí)行KiUnwaitThread函數(shù)來增加該隊列上活動線程的計數(shù)值。

最后,PostQueuedCompletionStatus這個Windows API將調(diào)用NtSetIoCompletion服務(wù)。該函數(shù)只是簡單的調(diào)用KeInsertQueue將自定義的完成通知包插入到完成端口的隊列中。

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)