乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Windows 多線程編程總結

       思考的軌跡 2011-10-18

      Windows 多線程編程總結

       

      關鍵字:多線程 線程同步 線程池 內核對象

      內核對象

      1 .1 內核對象的概念

      內核對象是內核分配的一個內存塊,這種內存塊是一個數(shù)據結構,表示內核對象的各種特征。并且只能由內核來訪問。應用程序若需要訪問內核對象,需要通過操作系統(tǒng)提供的函數(shù)來進行,不能直接訪問內核對象(Windows 從安全性方面來考慮的)。

      內核對象通過 Create* 來創(chuàng)建,返回一個用于標識內核對象的句柄,這些句柄 (而不是內核對象)可在創(chuàng)建進程范圍內使用,不能夠被傳遞到其他進程中被使用。

      1 .2 內核對象使用的計數(shù)

      因為內核對象的所有者是內核,而不是進程,所以何時撤銷內核對象由內核決定,而內核做這個決定的依據就是該內核對象是否仍然被使用。那么如何判斷內核對象是否被使用呢?可以通過內核對象的“使用計數(shù)”屬性,一旦這個值變成 0 了,內核就可以釋放該對象了。

      1 .3 創(chuàng)建內核對象

      1 .3.1 進程與句柄表

      每個進程在初始化的時候,將被分配一個句柄表,該句柄表中只存儲內核對象的句柄,不存儲用戶對象的句柄。句柄表的詳細結構微軟沒有公布,但是大致包含三個內容:內核對象句柄,內核對象地址,訪問屏蔽標志。

      微軟為何要將內核對象的句柄設置為進程相關的呢?理由有:

      l          不同的進程對內核對象的訪問權限是不同的,有必要區(qū)分對待

      l          如果句柄是全局的,則一個進程可以控制另外一個進程的句柄,破壞另外一個進程的句柄。

       

      1 .3.2 創(chuàng)建內核對象及操作系統(tǒng)內部機制

      利用 CreateSomeObject 的函數(shù)來創(chuàng)建內核對象。調用該函數(shù)的時候內核就為該對象分配一個內存塊,并進行初始化,然后內核再掃描該進程的句柄表,初始化一條記錄并放在句柄表中。

      1 .3.3 進程中使用內核對象的內部機制

      假設函數(shù) F 使用某個內核對象,其參數(shù)為 Handle1 ,則該函數(shù)內部需要查找該進程的句柄表,找出參數(shù)句柄對應的記錄,然后才能使用該內核對象。

      1 .4 關閉內核對象

      無論進程怎樣創(chuàng)建內核對象,在不使用該對象的時候都應當通過 Bool CloseHandle(HANDLE hobj) 來向操作系統(tǒng)聲明結束對該對象的訪問。為什么叫聲明呢?是因為此時也許還有其他進程對該對象的訪問,操作系統(tǒng)可能并不立即釋放該對象。操作系統(tǒng)需要做的是:從進程的句柄表中刪除該內核對象的記錄,另外再考察該內核對象的使用計數(shù)以決定是否需要釋放該對象。

      1 .5 內核對象的共享

      說到共享,與之孿生的就是共享權限。 Windows 內核對象的共享有三種方式:

      1 .5.1 繼承式共享(父子進程間)

      只有當進程是父子關系的時候,才能使用此種方式的共享。特別要注意的是繼承的是內核對象的句柄,內核對象本身是不具備繼承性。要達到這種繼承的效果需要做以下幾件事:

      l          在進程創(chuàng)建內核對象的時候,需要一個安全結構 sa  SECURITY_ATTRIBUTES 類型,以向 OS 聲明對象的訪問方式)作為參數(shù)。繼承式共享需要將結構的成員 sa.bInheritHandle 設置為 TRUE 。此時 OS 內部的處理式將進程的句柄表中的該對象的訪問屏蔽字段設置成“可繼承”。

      l          在創(chuàng)建子進程( CreateProcess 函數(shù))時,設置創(chuàng)建參數(shù) bInheritHandles  TRUE 。表示被創(chuàng)建的子進程可以繼承父進程中的所有可繼承內核對象。 OS 內部的處理是:復制父進程句柄表中的記錄到子進程的句柄表中,并使用相同的句柄值;為內核對象的使用計數(shù)器加 1 。

      特別說明:子進程能夠繼承的的內核對象僅局限于父進程創(chuàng)建它的時候所擁有的可繼承內核對象。子進程誕生后,父進程再搞出什么可繼承的東西,子進程是不能用的。這就需要在子進程中使用繼承的內核對象的時候需要慎重,以確定內核對象是否已被繼承了。

      利用 SetHandleinformation 方法可以隨時修改內核對象句柄的一些屬性,目前公開的句柄屬性有兩種,一種是該句柄是否能被繼承,另一種是該句柄是否能被關閉。

      1 .5.2 同名共享

      同名共享,不需要共享進程之間存在父子關系。但局限于內核對象是否支持這種共享方式。創(chuàng)建內核對象的Create 函數(shù)中是否包含 pszName 是該內核對象是否支持同名共享的標志。

      l          方法一:當 Process1 通過 CreateObject  …”someName” )創(chuàng)建了一個名字為 someName 的內核對象后, Process2 也調用了 CreateObject  …”someName” ),此時內核的動作是:在全局中查詢發(fā)現(xiàn)已經存在 someName1 的對象;為 Process2 的句柄表添加一條 Ojbect 的記錄,使用的句柄不確定;為 someName這個 Object 的引用計數(shù)器加 1 。

      l          方法二: Process2 使用 OpenObject  …”someName” )的方式來獲得對名 someName  Object 的句柄。用這種 Open 方法的時候,需要提供一個參數(shù)讓 OS 鑒權,以判定是否能夠以參數(shù)指定的方式來訪問內核對象。

      1 .5.3 復制內核對象的句柄的方式共享

      跨進程邊界的內核對象共享的另外一個方法是通過 DuplicateHandle 來復制內核對象句柄。

      如果要將 ProcessS 中的對象拷貝到 ProcessT 中則調用 DuplicateHandle 的進程一定要有對這兩個進程的訪問權,即句柄表中擁有這兩個進程內核對象的句柄記錄。

      線程的一般概念

      2 .1 視圖

      l          進程只是線程的容器,從來不執(zhí)行任何東西

      l          線程總是在某個進程中被創(chuàng)建

      l          線程在進程的地址空間中執(zhí)行代碼

      l          線程們共享進程中的所有內核對象

      線程的創(chuàng)建

      HANDLE CreateThread(

               PSECURITY_ATTRIBUTES psa,

               DWORD cbStack,

               PTHREAD_START_ROUTINE pfnStartAddr,

               PVOID pvParam,

               DWORD fdwCreate,

               PDWORD pdwThreadID);

       Windows 核心編程》 P124 介紹說應當使用編譯器提供的線程創(chuàng)建函數(shù),而不應當直接使用 CreateThread 。

      3 .1 CreateThread 調用的內核行為

      調用 CreateThread 后, OS 進行如下幾個動作:

      l          生成一個線程內核對象

      l          在進程空間內為線程分配堆??臻g

      因為線程的環(huán)境同于其所在進程的環(huán)境,所以創(chuàng)建的線程可以訪問進程中的所有資源,包括線程中所有的內核對象。

      線程銷亡

      4 .1 終止線程的方式:

      l          線程函數(shù)返回(最好使用這個方式,可以保證:線程種創(chuàng)建的 C++ 對象正常析構; OS 釋放線程堆棧內存; OS 將線程的退出碼設置為線程函數(shù)的返回值;系統(tǒng)將遞減該線程內核對象的的使用計數(shù)器【如果此時還有其他引用 …… ,見下面說明】。)

      l          調用 ExitThread (不能釋放 C++ 對象,所以最好不要使用這個方式。另外,如果非要調用也應當調用編譯器推薦的,如 _endThread  Windows 核心編程 P127 】)

      l          同進程內的其他線程(包括主線程)調用 TerminateThread (被撤銷線程得不到通知,不能釋放資源,盡量避免這種方式。另外這個函數(shù)是個異步函數(shù),返回時,線程不保證已經被撤銷,如果要觀察線程是否被撤銷,應當使用 WaitForSingleObject 

      l          包含線程的進程終止(應當避免這種方式)

      4 .2 線程退出時 OS 的行為

      l          線程內的所有用戶對象被釋放。

      l          線程的退出碼從 STILL_ACTIVE 改為傳遞給 ExitThread  TerminateThread 的代碼

      l          線程內核對象的狀態(tài)改為“已通知”

      l          如果線程為進程中的最后一個線程,則 OS 將進程當作已終止運行

      l          線程內核對象的引用計數(shù)器減 1 (一旦線程終止了,其他引用改線程內核對象將不能夠處理改線程的句柄,但是可以通過調用 GetExitcodeThread 來檢查 hThread 代表的線程是否已經終止運行了。)

      線程同步

      5 .1 線程同步的起因以及解決之道

      5 .1.1 共用資源型:多個線程需要訪問同一個資源的時候,為了保證資源不被破壞,需要線程對資源的訪問具有原子性。

      5 .1.2 依賴型:一個線程等待另外一個線程某件事情完成后才能執(zhí)行 _ 可以通過手動事件的方式互相通知。

      5 .2 線程同步種類細分

      同步起因

      同步種類

      同步方法備注

      共用資源

      多個線程對共用變量做加減操作

      互鎖函數(shù)族之: InterlockedExchangeAdd

      共用資源

      多個線程對公共變量、指針做賦值操作

      互鎖函數(shù)族之: InterlockedExchange ,InterlockedExchangepoint

      共用資源

      多個線程需要根據對公共變量、指針的判斷做操作選擇

      互鎖函數(shù)族之: InterlockedCompareExchange

                    InterlockedCompareExchangePointer

      共用資源

      復雜數(shù)據結構(非單值),不適合互鎖函數(shù)族處理的

      用“關鍵代碼”的方式,關鍵代碼中要注意 1 、要盡量的快速處理完,以防止其他等待線程等待太長時間 2 、線程等待過程中由用戶模式切換到內核模式,耗費 1000  CPU 周期,時間比較長。 3 、只能對單個進程中的線程進行同步)

      InitializeCriticalSection;

      EnterCriticalSection;

      LeaveCriticalSection;

      DeleteCriticalSection;

      處理線程同步的一種方法

      對線程同步做的一個抽象,線程的同步本質上都是依賴于某個其他事件的發(fā)生,用軟件的方法來對所依賴的事件做一個抽象,將有助與程序編寫的簡捷

      CreateEvent

      Event 的重要屬性有一個是“自動” or “手動”,如果是自動的,則在某個線程用 Wait ××成功等待到事件的“通知”狀態(tài)后,則事件狀態(tài)立刻變成“未通知”狀態(tài),以保證同時對資源訪問的線程只有一個。

      原則上不算線程同步范疇,而屬于對 wait** 的一種應用方式

      一個可以作為定時器的內核對象,Waitable Timer

      CreateWaitableTimer

      SetWaitableTimer,

      CancelWaitableTimer

      共用資源

      一組線程對一組同樣性質的資源的爭用,則這組資源需要有所表示,以告知線程們是否有空閑的給以為他們服務,以信號量機制實現(xiàn)

      CreateSemaphore,ReleaseSemaphore

      共用資源

      一組線程對一個單一的資源的爭用,需要有一種機制保證同一個事件只有一個線程能得到資源。以Mutex 方式實現(xiàn)

      CreateMutex

      ReleaseMutex

      與關鍵代碼的差別在于:

      1、    允許不同進程的線程之間同步

      2、    內核對象,用戶模式和內核模式切換的時候需要更多的 CPU 開銷

      特別說明: WaitForSingleObject/WaitForMultipleObject 是抑制線程本身的一種手法,配合以共用資源對象或所依賴的其他對象“通知狀態(tài)”的原子性變化,以達到線程在爭用資源、互相依賴時執(zhí)行的順序化,從而達到同步的目的。

      綜上:其實 Windows 的線程同步機制是提供了一組不同情況下的資源爭用處理辦法而已。與此同時推出的Wait ××卻可以帶來很多其他好處,甚至部分緩解 C++ 語言沒有事件機制的缺憾,部分達到了 JAVA,C# 中事件機制的效果,為 Oberserve 模式的實現(xiàn)做了些貢獻。

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多