• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            loop_in_codes

            低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

            IOCP與線程

            author : Kevin Lynx

             

            什么是完成包?

            完成包,即IO Completion Packet,是指異步IO操作完畢后OS提交給應(yīng)用層的通知包。IOCP維護(hù)了一個(gè)IO操作結(jié)果隊(duì)列,里面
            保存著各種完成包。應(yīng)用層調(diào)用GQCS(也就是GetQueueCompletionStatus)函數(shù)獲取這些完成包。

            最大并發(fā)線程數(shù)

            在一個(gè)典型的IOCP程序里,會(huì)有一些線程調(diào)用GQCS去獲取IO操作結(jié)果。最大并發(fā)線程數(shù)指定在同一時(shí)刻處理完成包的線程數(shù)目。
            該參數(shù)在調(diào)用CreateIoCompletionPort時(shí)由NumberOfConcurrentThreads指定。

            工作者線程

            工作者線程一般指的就是調(diào)用GQCS函數(shù)的線程。要注意的是,工作者線程數(shù)和最大并發(fā)線程數(shù)并不是同一回事(見(jiàn)下文)。工作者
            線程由應(yīng)用層顯示創(chuàng)建(_beginthreadex 之類(lèi))。工作者線程通常是一個(gè)循環(huán),會(huì)不斷地GQCS到完成包,然后處理完成包。

            調(diào)度過(guò)程

            工作者線程以是否阻塞分為兩種狀態(tài):運(yùn)行狀態(tài)和等待狀態(tài)。當(dāng)線程做一些阻塞操作時(shí)(線程同步,甚至GQCS空的完成隊(duì)列),線程
            處于等待狀態(tài);否則,線程處于運(yùn)行狀態(tài)。

            另一方面,OS會(huì)始終保持某一時(shí)刻處于運(yùn)行狀態(tài)的線程數(shù)小于最大并發(fā)線程數(shù)。每一個(gè)調(diào)用GQCS函數(shù)的線程O(píng)S實(shí)際上都會(huì)進(jìn)行記錄,
            當(dāng)完成隊(duì)列里有完成包時(shí),OS會(huì)首先檢查當(dāng)前處于運(yùn)行狀態(tài)的工作線程數(shù)是否小于最大并發(fā)線程數(shù),如果小于,OS會(huì)按照LIFO的順
            序讓某個(gè)工作者線程從GQCS返回(此工作者線程轉(zhuǎn)換為運(yùn)行狀態(tài))。如何決定這個(gè)LIFO?這是簡(jiǎn)單地通過(guò)調(diào)用GQCS函數(shù)的順序決定的。

            從這里可以看出,這里涉及到線程喚醒和睡眠的操作。如果兩個(gè)線程被放置于同一個(gè)CPU上,就會(huì)有線程切換的開(kāi)銷(xiāo)。因此,為了消
            除這個(gè)開(kāi)銷(xiāo),最大并發(fā)線程數(shù)被建議為設(shè)置成CPU數(shù)量。

            從以上調(diào)度過(guò)程還可以看出,如果某個(gè)處于運(yùn)行狀態(tài)的工作者線程在處理完成包時(shí)阻塞了(例如線程同步、其他IO操作),那么就有
            CPU資源處于空閑狀態(tài)。因此,我們也看到很多文檔里建議,工作者線程數(shù)為(CPU數(shù)*2+2)。

            在一個(gè)等待線程轉(zhuǎn)換到運(yùn)行狀態(tài)時(shí),有可能會(huì)出現(xiàn)短暫的時(shí)間運(yùn)行線程數(shù)超過(guò)最大并發(fā)線程數(shù),這個(gè)時(shí)候OS會(huì)迅速地讓這個(gè)新轉(zhuǎn)換
            的線程阻塞,從而減少這個(gè)數(shù)量。(關(guān)于這個(gè)觀點(diǎn),MSDN上只說(shuō):by not allowing any new active threads,卻沒(méi)說(shuō)明not allowing
            what)

            調(diào)度原理

            這個(gè)知道了其實(shí)沒(méi)什么意義,都是內(nèi)核做的事,大致上都是操作線程control block,直接摘錄<Inside IO Completion Ports>:

            The list of threads hangs off the queue object. A thread's control block data structure has a pointer in it that
            references the queue object of a queue that it is associated with; if the pointer is NULL then the thread is not
            associated with a queue.

            So how does NT keep track of threads that become inactive because they block on something other than the completion
            port" The answer lies in the queue pointer in a thread's control block. The scheduler routines that are executed
            in response to a thread blocking (KeWaitForSingleObject, KeDelayExecutionThread, etc.) check the thread's queue
            pointer and if its not NULL they will call KiActivateWaiterQueue, a queue-related function. KiActivateWaiterQueue
            decrements the count of active threads associated with the queue, and if the result is less than the maximum and
            there is at least one completion packet in the queue then the thread at the front of the queue's thread list is
            woken and given the oldest packet. Conversely, whenever a thread that is associated with a queue wakes up after
            blocking the scheduler executes the function KiUnwaitThread, which increments the queue's active count.

            參考資料

            <Inside I/O Completion Ports>:
            http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx
            <I/O Completion Ports>:
            http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx
            <INFO: Design Issues When Using IOCP in a Winsock Server>:
            http://support.microsoft.com/kb/192800/en-us/

            posted on 2008-06-23 17:32 Kevin Lynx 閱讀(4848) 評(píng)論(3)  編輯 收藏 引用 所屬分類(lèi): network

            評(píng)論

            # re: IOCP與線程 2008-06-23 23:45 飯中淹

            @Kevin Lynx
            寫(xiě)iocp應(yīng)用的時(shí)候,我覺(jué)得最好能夠?qū)崿F(xiàn)工作線程就地組包,然后在組包之后,在工作線程內(nèi)就地處理,這樣是對(duì)iocp和cpu資源的最佳化利用。

            還有,多謝你的幫助,我才糾正了對(duì)iocp的錯(cuò)誤理解。

              回復(fù)  更多評(píng)論   

            # re: IOCP與線程 2010-06-04 11:02 我是豬

            @飯中淹
            錯(cuò)了 這樣會(huì)浪費(fèi)效能  回復(fù)  更多評(píng)論   

            # re: IOCP與線程 2010-06-29 09:55 zhengxf

            你好,我也認(rèn)為寫(xiě)iocp應(yīng)用的時(shí)候, 應(yīng)該工作線程就地組包,然后在組包之后,在工作線程內(nèi)就地處理, 不知道"飯中淹" 老兄有何高見(jiàn),能分享一下嗎.
              回復(fù)  更多評(píng)論   

            精品久久久无码人妻中文字幕| 粉嫩小泬无遮挡久久久久久| 久久e热在这里只有国产中文精品99 | 久久亚洲av无码精品浪潮| 色播久久人人爽人人爽人人片aV| 亚洲精品成人网久久久久久| 久久久无码精品亚洲日韩按摩| 国产成人无码精品久久久免费 | 亚洲一本综合久久| 国产精品久久久香蕉| 精品一区二区久久| 久久精品国产日本波多野结衣| 老司机国内精品久久久久| 亚洲精品乱码久久久久久蜜桃 | 国内精品久久久久久久久电影网| 亚洲精品无码久久久久| 久久综合久久鬼色| 精品久久久久久中文字幕| 精品久久久中文字幕人妻| 久久噜噜久久久精品66| 亚洲国产精品久久久久| 色综合久久综合中文综合网| 国产精品久久久香蕉| 久久性精品| 久久露脸国产精品| 国内精品免费久久影院| 91精品久久久久久无码| 久久精品国产91久久综合麻豆自制 | 老男人久久青草av高清| 久久婷婷色综合一区二区| 亚洲国产成人久久精品影视| 国产精品久久永久免费| jizzjizz国产精品久久| 狠狠色婷婷久久一区二区三区| 熟妇人妻久久中文字幕| 久久久久久久久无码精品亚洲日韩| 无码国内精品久久人妻| 久久综合给合久久狠狠狠97色69| 色综合久久久久综合体桃花网| 人妻无码久久一区二区三区免费 | 久久精品aⅴ无码中文字字幕不卡|