日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

线程基础知识——Windows核心编程学习手札系列之六

發布時間:2025/4/16 windows 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程基础知识——Windows核心编程学习手札系列之六 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程基礎知識

——Windows核心編程學習手札系列之六

線程與進程一樣由兩部分構成:一是線程的內核對象,操作系統用它來對線程實施管理,也是系統用來存放線程統計信息的地方;二是線程堆棧,用于維護線程在執行代碼時需要的所有函數參數和局部變量。進程是靜止的,不執行代碼,只是線程的容器,線程總是在某個進程環境中創建的,且其整個壽命周期都在該進程中,線程在進程的地址空間中執行代碼和操作數據。在單進程中,存在多個線程運行,這些線程共享進程的地址空間,執行相同代碼和操作相同數據,還共享內核對象句柄(句柄表依賴于進程存在而非線程)。進程使用的資源比較多,需要為進程創建一個虛擬地址空間(需要系統很多資源);要保留眾多記錄(占用大量內存);文件如exedll要加載到地址空間(需要文件資源),相比下線程只需要一個內核對象和一個堆棧,需要少量內存維護記錄即可。線程的開銷比進程少,在開發中始終設法用線程來解決編程問題是最優選擇。

每個進程在初始化時,系統會為其創建一個主線程,該線程與C/C++運行期庫的啟動代碼一并開始運行,啟動代碼調用進入點函數(main/wmain/WinMain/wWinMian)并繼續運行直到進入點函數返回并且C/C++運行期庫的啟動代碼調用ExitProcess為止。每個線程都有進入點函數,線程從這個進入點開始運行,主線程的進入點函數是main/wmain/WinMain/wWinMain,如想要在進程中創建輔助線程,也需要一個進入點函數,如同下面的代碼:

DWORD WINAPI ThreadFunc(PVOID pvParam){

?????? DWORD dwResult=0;

?????? ……

?????? return (dwResult);

}

線程函數可以執行你所要執行的任務,線程函數達到結尾處且返回,線程終止運行,堆棧的內存被釋放,同時線程的內核對象被遞減,如使用計數為零,其內核對象被撤消。對線程函數應該認識到的是:1)主線程的進入點函數名字必須是main/wmain/wWinMain/WinMain這四個,其他線程函數可以使用任何名字,但不同線程之間的函數名必須不同,否則編譯器或鏈接程序會認為單個函數創建了多個實現函數;2)線程函數可以傳遞單個參數,參數含義自定義而不由操作系統來定義;3)線程函數必須返回一個值,作為該線程的推出代碼;4)線程函數應盡可能使用函數參數和局部變量,如使用靜態變量和全局變量,多個線程可以同時訪問這些變量,可能破壞變量的內容。

創建新的線程,可在正運行的線程中調用CreateThread函數來實現:

HANDLE CreateThread(

???????????????????? PSECURITY_ATTRIBUTES psa,

???????????????????? DWORD cbStack,

???????????????????? PTHREAD_START_ROUTINE pfnStartAddr,

???????????????????? PVOID pvParam,

???????????????????? DWORD fdwCreate,

??????????????????? PDWORD pdwThreadID);

CreateThread被調用時,系統創建一個線程內核對象,是操作系統用來管理線程的較小數據結構,是關于線程統計信息組成的小型數據結構。系統從進程的地址空間中分配內存供線程的堆棧使用,新線程運行的進程環境與創建線程一樣,新線程可以訪問進程的內核對象的所有句柄、所有內存和在這個進程中的其他線程的堆棧。CreateThread函數是Windows提供的用來創建線程,如在編寫C/C++代碼,不應調用該函數,而應該使用Visual C++運行期庫函數_beginthreadex來創建新線程。一個原則就是盡量采用編譯器供應商自己的創建線程函數來代替CreateThreadWindows函數。

函數CreateThread的第一個參數psa是指向SECURITY_ATTRIBUTES結構的指針,如僅設置該線程的內核對象為默認安全屬性,可以直接傳遞NULL;如希望子進程能夠繼承該線程對象的句柄,則需要設定一個SECURITY_ATTRIBUTES結構,它的bInheritHandle成員被初始化為TURE值。

函數CreateThread的第二個參數cbStack用于設定線程可以將多少地址空間用于自己的堆棧。當CreateProcess啟動一個進程時,在內部調用CreateThread來對進程的主線程進行初始化。對于cbStack參數來說,CreateProcess使用存在在可執行文件中的一個值,可使用鏈接程序的/STACK開關來控制cbStack值:/STACK:[reverse][.commit]reserve參數用于設定系統應該為線程堆棧保留的地址空間量,默認值是1MBcommit參數用于設定開始時應該承諾用于堆棧保留區的物理存儲器的容量,默認值是 1頁。當線程中的代碼執行時,可能需要多個頁面的存儲器,當線程溢出它的堆棧時,就生成一個異常條件,系統抓取該異常條件,并將另一頁用于保留空間,使得線程的堆棧能夠根據需要動態地擴大。當調用CraeteThrad時,如果cbStack傳遞的值不是0,就能使該函數將所有的存儲器保留并分配給線程的堆棧,由于所有的存儲器預先作了分配,因此可以確保線程擁有指定容量的可用堆棧存儲器。保留空間的容量可以在是/STACK鏈接設定的值也可以是cbStack的值,誰大用誰。分配的存儲器容量則與傳遞的cbStack一致,如將0傳遞給cbStack參數,CreateThread 就保留一個區域,并且將鏈接程序嵌入exe文件的/STACk鏈接程序開關信息指明的存儲器容量分配給線程堆棧。保留空間的容量用于為堆棧設置一個上限,這樣可以抓住代碼中的循環遞歸錯誤,防止遞歸函數無限制地循環調用自己和創建新堆棧,從而消耗掉存儲資源。

函數CreateThread的第三個參數pfnStartAddr指明想要新線程執行的線程函數地址。函數CreateThread的第四個參數pvParam作為將初始化值傳遞給線程函數的手段,既可以是數字值,也可以是指向包含其他信息的一個數據結構指針。創建多個線程,使這些線程擁有和起始點相同的函數地址,如實現一個Web服務器,創建一個新線程處理每個客戶機的請求,每個線程都知道自己正在服務于哪個客戶端的請求,這需要在創建線程時傳遞不同的pvParam參數。

函數CreateThread的第五個參數fdwCreate可以設定用于控制創建線程的其他標志,如果該值是0,那線程創建后立即進行調度,如該值是CREATE_SUSPENDED,系統可以完整地創建線程并對它進行初始化,但要暫停該線程的運行,使其無法進行調度。CREATE_SUSPENDED標志使得應用程序能夠在它有機會執行任何代碼之前修改線程的某些屬性,由于這種必要性很少,所以通常不用。函數CreateThread的第六個參數pdwThreadIDDWORD類型的一個有效地址,CreateThread使用這個地址來存放系統分配給新線程的ID。

終止線程的運行,方法有:1)線程函數返回(最優);2)調用ExitThread函數,線程將自行撤消(最好不用);3)同一個進程或另一個進程中的線程調用TerminateThread函數(避免使用該方法);4)包含線程的進程終止運行(避免使用)。線程函數返回可確保所有線程資源被正確地清除:1)在線程函數中創建的所有C++對象均將通過它們的撤消函數正確地撤消;2)操作系統將正確地釋放線程堆棧使用的內存;3)系統將線程的推出代碼(在線程的內核對象中維護)設置為線程函數的返回值;4)系統將遞減線程內核對象的使用計數??梢宰尵€程強制終止運行,通過調用VOID ExitThread(DWORD dwExitCode)函數來實現,該函數將終止線程的運行,并導致操作系統清除該線程使用的所有操作系統資源,但C++資源如C++類對象將不被撤消,基于這個原因,最好從線程函數返回,而不是通過調用ExitThread函數來返回。如創建線程一樣,應盡量使用Visual C++運行期庫函數_endthreadex來終止線程運行。TerminateThread函數也可終止線程運行:BOOL TerminateThread(HANDLE hThread,DOWRD dwExitCode),能夠撤消任何線程而ExitThread只能撤消調用的線程,其中hThread作為參數用于標識被終止運行線程的句柄。TerminateThread函數是異步運行的函數,告訴系統終止線程的運行,但當函數返回時,不能保證線程被撤消,如果需要確切知道線程終止運行,需調用WaitForSingleObject或者類似函數,傳遞線程的句柄。當線程終止運行時,會發生下列操作:1)線程擁有的所有用戶對象均被釋放,在Windows中大多數對象都是由包含創建這些對象的線程的進程所擁有的,但是一個線程擁有兩個用戶對象,即窗口和掛鉤,當線程終止運行時,系統會自動撤消任何窗口,并且卸載線程創建的或安裝的任何掛鉤,其他對象只有在擁有線程的進程終止運行時才被撤消;2)線程的退出代碼從STILL_ACTIVE改為傳遞給ExitThreadTerminateThread的代碼;3)線程內核對象狀態變為已通知;4)如果線程是進程中的最后一個活動線程,系統也將進程視為已終止運行;5)線程內核對象的使用計數遞減1。一旦線程不再運行,系統中就沒有別的線程能夠處理該線程的句柄,然而別的線程可以用GetExitCodeThread來檢查由hThread標識的線程是否已經終止運行,如果它已經終止運行則確定它的退出代碼:BOOL GetExitCodeThread(HANDLE hThread,PDWORD pdwExitCode),退出代碼的值在pdwExitCode指向的DWORD中返回,如果調用GetExitCodeThread函數時線程還未終止運行,該函數就用STILL_ACTIVE標識符(定義為0x103)填入DWORD,如果函數運行成功便返回TURE值。

????????????????????????????????????????? ?如非? 2008-12-16

?

總結

以上是生活随笔為你收集整理的线程基础知识——Windows核心编程学习手札系列之六的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。