1. 程式人生 > >內核對象&句柄

內核對象&句柄

指針 其他 維護 自動 試圖 是個 通過 可能 img

目錄

  • 1 內核對象的概念
  • 2 內核對象的使用計數
  • 3 句柄
  • 4 句柄表

??項目工程代碼中設計句柄的使用,一時不知句柄是何物,通過查閱自學之後,對句柄及其使用有一個初步的了解。分享出來,算是拋磚引玉吧。
??在闡述句柄之前,先說明一下內核對象。

1 內核對象的概念

??內核對象就是一個內存塊,有內核分配,只能由內核訪問。

技術分享圖片

??內存塊是一種數據結構,其中的數據成員負責維護該對象的相應信息,這個數據結構以及其中的數據成員只能由內核訪問,應用程序是無法訪問到的,更別說修改其中的數據成員了。

??如何訪問這些內核對象(內存塊)呢?

??操作系統為使用者封裝了一組API,使用者可以通過這些API訪問內核對象(內存塊)。比如,創建內核對象(內存塊)時,使用者調用API中的創建內核對象函數,由內核創建一個內核對象(分配一塊內存)。

??內核對象創建好之後,用一個句柄來標識該內核對象(內存塊),這個句柄作為函數值返回。這個句柄就是個整數,32位機句柄就是32bit,64位機句柄就是64bit,同一進程中的任何線程都能使用這個句柄,當需要操作內核對象(內存塊)時,通過API將這個句柄傳給內核,內核就知道是對哪個內核對象(內存塊)進行操作了。

創建內核對象,引出句柄。 

2 內核對象的使用計數

??在應用程序中,可能有多個進程,這些進程中的一個或多個可能會訪問同一個內核對象。內核對象有使用就會有撤銷,那麽什麽情況下內核會撤銷某個內核對象呢。內核的使用計數就派上用場了。使用計數是內核對象這個數據結構的數據成員,通過使用計數就能知道該內核對象被多少個進程使用。開始創建內核對象時,使用計數置為1,之後每多一個不同的進程使用該內核對象,使用計數就自加1.

??無論什麽方式創建內核對象,我們都需要調用 ClosseHandle 向系統表明我們已經結束使用對象.就在 CloseHandle 函數返回前,它會清除進程句柄表中對應的記錄項 -- 這個句柄現在對我們的進程來說是無效的,不要在試圖利用它.換句話說,一旦調用 CloseHandle

, 我們的進程就不能訪問那個內核對象.

??當進程關閉時,內核自動訪問該進程仍然打開的內核對象的使用計數,該進程關聯的每個內核對象的使用計數自減1,當使用計數減到0時,內核就會撤銷該內核對象。

??內核對象的使用計數有些像智能指針。

3 句柄

??內核對象創建好之後,用一個句柄來標識該內核對象(內存塊),這個句柄作為函數值返回。這個句柄就是個整數,32位機句柄就是32bit,64位機句柄就是64bit。

??在同一進程中,一個句柄對應一個內核對象,我們在訪問內核對象(內存塊)時,就是通過句柄告訴內核,我要訪問哪個內核對象。

??通俗的說,句柄,就是個編號,操作系統對於我們來說就是個黑箱,我們通過句柄向操作系統要東西。

4 句柄表

??當一個進程被初始化時,系統要為它分配一個句柄表.該句柄表只用於內核對象,不用於用戶對象或GDI對象.句柄表也是由內核操作。進程表包含的元素如下所示:

索引  內核對象  內存塊的指針訪問屏蔽(標誌位的DWORD)  標誌(標誌位的DWORD)

??進程被初次初始化時,句柄表是空的。

??當進程中的線程創建內核對象時,內核給該對象分配一塊內存,並對其初始化。內核遍歷該進程的句柄表,找出一個空閑位置,設置內核對象,內存塊指針,訪問掩碼,標識,並獲取該位置的索引,作為函數值返回,這個索引就是我們所說的句柄。這個句柄只能有同一個進程的所有線程使用, 系統用索引來表示內核對象的信息保存在進程句柄表中的具體位置。其他進程不能使用該進程的索引,因為句柄表不同(每個進程有一個單獨的句柄表)。

??所以,句柄實際上是句柄表的索引。可以這麽理解,指針指向一塊內存空間,那麽句柄就是指向其對應的內核對象,通過操作系統提供的API吧句柄傳給內核,內核就知道要操作那個內核對象。

內核對象&句柄