1. 程式人生 > >Win32多線程之核心對象

Win32多線程之核心對象

清理 roc dll 擁有 nal cti 多個進程 mutex 依賴

  CreateThread()傳回兩個值,用以識別一個新的線程。第一個值是個Handle, 這也是CreateThread()的返回值,大部分與線程有關的API函數都需要它。第二個值是由lpThreadId帶回來的線程ID。線程ID是一個全局變量,可以獨一無二地表示系統中任一進程中的某個線程。AttachThreadInput()和PostThreadMessage()就需要用到線程ID,這兩個函數允許你影響其他人(線程)的消息隊列。調試器和進程觀察器也需要 線程ID,為了安全防護的緣故,你不可能根據線程的ID而獲得其handle。
  CreateThread()傳回來的handle被稱為一個核心對象(kernal Object)。核心對象其實和所謂的GDI對象,如畫筆,畫刷或DC是差不多的,只不過它由Kernel.dll來管理,而畫筆,畫刷由GDI32.dll來管理。兩種對象之間有許多相似性。
  GDI對象是Windows的基礎部分。在Win16或Win32中它們都是由操作系統管理。通常你不需要知道其數據格式。例如,你可能會調用SelectObject()或ReleaseObject()以處理GDI對象:Windows隱藏了實現細節,只是給你一個HDC或者一個HBRUSH,那都是對象的handle。
  核心對象以HANDLE為使用時的參考依據,與GDI的HBRUSH,HPEN,HPALETTE以及其他handles不同的是,只有一種handle可以代表核心對象。所謂handle,其實是個指針,指向操作系統內存空間的某樣東西,那東西不允許你直接取得。你的程序不能夠直接取用它,為的是維護系統的完整性與安全性。

 下面是各種Win32核心對象的清單。

  1)進程(processes)

  2)線程(threads)

  3) 文件(files)

  4)事件(events)

  5)信號量(semaphores)

  6)互斥器(mutexes)

  7)管道(Pipes,分為named和anonymous兩種)

  其中事件,信號量,互斥器,這些核心對象可以用來整合許多的線程或進程。

  註意:Critical Sections(臨界區域、關鍵區域)並不是核心對象。

  GDI對象和核心對象之間有一個主要的不同,GDI對象有單一擁有者,不是進程就是線程。核心對象可以有一個以上的擁有者,甚至可以跨進程。為了保持對每一位擁有者的追蹤,核心對象保持了一個引用計數器,以記錄有多少handles對應次對象,對象中也記錄了那一個進程或線程是擁有者。如果你調用CreateThread()或是其它會傳回handle的函數,引用計數便累加1.當你調用CloseHandle()時,引用計數便遞減1.一旦引用計數降至0,這一核心對象即自動被摧毀。

  面對一個打開的對象,區分其擁有者是進程或者是線程。是件很重要的事情。因為這回=會決定系統何時做清除善後(clean up)操作。所謂
clean up操作,包括將該進程或線程所擁有的每一個對象的引用計數減1,若有必要,則對象會被摧毀掉。程序員不能選擇由進程或者線程擁有對象,一切得視對象類型而定。
由於引用計數的設計,對象有可能在產生該對象之進程結束之後還繼續幸存。Win32提供各種機制,讓其他進程得以取得一個核心對象的handle。如果某個進程握有某個核心對象的handle,而該對象的原創者(進程)已經“作古”了,次核心對象並不會被摧毀。
  CloseHandle()的重要性

當你完成你的工作後,應該調用CloseHandle釋放核心對象。

 BOOL CloseHandle(HANDLE hObject);

  參數
  hObject 代表一個已打開之對象handle
  返回值

  如果成功,CloseHandle()返回TRUE,如果失敗則傳回FALSE.此時你可以調用GetLastError()獲知失敗原因。

如果一個進程沒有在結束之前對它所打開的核心對象調用CloseHandle(),操作系統會自動把哪些對象的引用計數下降1.雖然你可以依賴系統做實體(physical)上的清除(cleanup)工作,然而邏輯上的清楚工作又是完全不同的一回事,特別是如果你有多個進程的話,因為系統並不知道對象實際代表什麽意義,
所以它不可能知道解構順序是否重要。
如果一個進程常常產生“worker 線程”而老是不關閉線程的handle,那麽這個進程可能最終有數百甚至數千個開啟的“線程核心對象”留給操作系統去清理,這樣的資源泄漏可能會對效率帶來負面的影響。
你不可以依賴“因線程的結束而清理所有被這一線程產生的核心對象”。虛度對象,例如文件,是被進程所擁有,而非被線程擁有。在進程結束之前不能夠清理它們。

Win32多線程之核心對象