核心物件只是作業系統核心分配的乙個記憶體塊,並且只能由作業系統核心訪問。該記憶體塊是一種資料結構,它的成員負責維護該物件的各種資訊。windows提供一組函式建立和操作核心物件。呼叫乙個建立核心物件的函式,函式會返回乙個控制代碼,該控制代碼標識了這個核心物件,這個控制代碼可由當前程序中的所有執行緒呼叫。也可以通過跨程序邊界共享核心物件,讓其他的程序呼叫。
使用計數。核心物件有個使用計數資料成員,標識核心物件被多少個程序所使用。大部分情況是核心物件只被建立它的程序所有使用,當這個程序退出時,核心物件的使用計數就會減一,如果核心物件的使用計數為0時,核心物件就會自動銷毀,如果核心物件被多個程序使用時,它的生命週期就可能比建立它的程序要長。只要核心物件的使用計數不為0,它就不會銷毀,當當前程序退出時,只要有其他程序使用這個核心物件,它就不會銷毀。但是我們也不用擔心核心物件導致的記憶體洩露,就算程序沒有手動關閉核心物件,程序在退出的時候,會檢查自己的控制代碼表,如果控制代碼表中有使用的核心物件,作業系統會為我們關閉這些控制代碼,被這些控制代碼引用的核心物件的使用計數就會減一,如果使用計數為0,核心物件就會自動銷毀。從上面我們可以看出,核心物件並沒有和建立它的程序所繫結,建立它的程序退出了,核心物件可能還存活,核心物件的操作所有者是作業系統,而不是程序。
核心物件的安全性。核心物件可以用乙個安全描述符來保護,安全描述符描述了誰是該物件的擁有者,那些組和使用者可以訪問或使用這些物件,這個物件是否可以被繼承等。security_attributes這個結構體就是用於安全描述的。其結構如下:
typedef struct _security_attributes security_attributes;
區分乙個物件是否是核心物件就可以看建立物件函式的引數中有沒有security_attributes這個引數,有的就是核心物件,沒有的就不是核心物件。有了這個結構就將核心物件保護起來了,其他物件就不能隨便訪問它,也就不能破壞它的記憶體結構。
程序核心物件控制代碼表。乙個程序在初始化時,系統將為它分配乙個控制代碼表。這個控制代碼表僅供核心物件使用,不適用於使用者物件和gdi物件,控制代碼表的結構大致包括:
1:索引
2:指向核心物件記憶體塊的指標
3:訪問掩碼
4:標誌
乙個程序在首次初始化的時候,其控制代碼表為空,即程序沒有引用任何核心物件,當程序中的乙個執行緒呼叫乙個建立乙個核心物件的函式時,核心將會為這個核心物件分配並初始化乙個記憶體塊,然後核心會掃瞄控制代碼表,找到乙個空白的記錄項,指標成員會指向剛建立的核心物件的記憶體位址,訪問掩碼會設定成擁有完全訪問的許可權,如果這個核心物件可以被繼承,標誌成員將設為1,如果不能被繼承就是0。當呼叫關閉核心物件的函式closehandle,引用該核心物件的程序中的控制代碼表中相應的記錄項就會被清除,當程序退出的使用控制代碼表中的所有記錄都會被清除,所有被使用的核心物件的使用計數都會減一,使用計數為0的核心物件就會自動銷毀。就算沒有手動關閉核心物件,程序退出了也不會出現核心物件洩露,當乙個核心物件沒有被任何程序引用時會自動銷毀的。
跨程序邊界共享核心物件。在很多時候需要再不同的程序中共享核心物件,如訊號量,互斥量和事件允許不同的程序中的執行緒同步執行,這時就需要共享核心物件。共享核心物件的方式有三種:
1:使用核心物件控制代碼繼承
2:為物件命名
3:複製物件控制代碼
1:使用核心物件控制代碼繼承。只有程序之間有父子關係時才能使用核心物件控制代碼繼承。若乙個物件程序允許其子程序繼承它的控制代碼,那麼它在建立可被繼承的核心物件時,建立核心物件的函式的引數security_attributes的成員binherithandle要設為true,這樣當父程序建立乙個子程序時,子程序就會複製父程序的控制代碼表中可以被繼承的控制代碼到自己的控制代碼表中。每個程序都有自己的控制代碼表,父程序與子程序之間並不是共享控制代碼表,所以當子程序建立好了後,父程序在建立乙個可以被繼承的核心物件時,只程序並不能訪問這個核心物件,因為它根本不知道這個核心物件的存在,當然子程序建立自己的核心物件時,父程序也是不知道的。因為微軟沒有寫多於的**來複製這些可被繼承的控制代碼到相應的控制代碼表中。所以說核心物件並不是真的繼承,而是繼承了核心物件的控制代碼。也就是說控制代碼只是核心物件的乙個指標,而不是核心物件的乙個成員。
我們可以通過函式sethandleinformation來標誌核心物件是否可乙個被子程序繼承。如有乙個可以被子程序繼承的核心物件,但你不想讓某個程序繼承,在建立這個子程序之前將該核心物件標記為不可繼承,在建立子程序,然後在呼叫函式sethandleinformation將核心物件標記為可以繼承,這個其他即將要建立的子程序就可以共享這個核心物件。
sethandleinformation(
__in handle hobject,//核心物件的控制代碼
__in dword dwmask,//告訴函式想更改哪個或哪些標誌
__in dword dwflags//是否可以被繼承
);2:為物件命名。很多建立核心物件的函式都有乙個引數lpname指定核心物件的名字,如以下兩個函式:
createmutexa(
lpsecurity_attributes lpmutexattributes,
bool binitialowner,
lpcstr lpname
);createeventw(
lpsecurity_attributes lpeventattributes,
bool bmanualreset,
bool binitialstate,
lpcwstr lpname
);最後乙個引數lpname的值就是核心物件的名稱,如果為這個引數傳入null,表示不想為該核心物件命名。如下面的**建立了乙個名為cth的互斥量核心物件。
handle mutexprocessa=createmutex(null,false,text("cth"));
另乙個程序b也想建立乙個互斥量核心物件,**如下:
handle mutexprocessb=createmutex(null,false,text("cth"));
核心並不會馬上建立乙個互斥量核心物件,而是會先檢查是否存在乙個名為cth的互斥兩核心物件,若有,判斷是否有許可權,若有,會將已經存在的互斥量的控制代碼複製到程序b的控制代碼表中,將互斥量的控制代碼返回給mutexprocessb,若不存在名為cth的物件當然是建立乙個,若是存在乙個名為cth的其他型別的核心物件那就會建立失敗,函式返回null。還是那句話核心物件屬於作業系統,跟是哪個程序建立它關係並不大,這樣也就很容易實現核心物件的共享了。
3:複製物件控制代碼。使用函式duplicatehandle。
duplicatehandle(
handle hsourceprocesshandle,
handle hsourcehandle,
handle htargetprocesshandle,
lphandle lptargethandle,
dword dwdesiredaccess,
bool binherithandle,
dword dwoptions
);這個函式獲取乙個程序控制代碼表中的乙個記錄項,然後在另乙個程序的控制代碼表中建立該記錄項的乙個副本,然後另乙個程序也就能訪問這個核心物件了。
正則核心物件詳解 三
前言 很感謝大家對正規表示式文章的支援,這篇文章是這個系列的最後一節了,但是正如之前所說的,這裡將的僅僅只是怎麼用.net的正規表示式類,但是,對正規表示式的引擎的內部機制沒有提及,如果大家需要,我會繼續寫下有關內部機制的問題.今天的內容如下 1.match物件的使用 2.group物件的使用 3....
正則核心物件詳解 二
前言 大家反映文章的排版有問題,我在寫文章的時候也一直注意這個問題,寫的時候排版不錯,但是發上去了就變了,我也不知道怎麼回事,希望大家理解 謝謝各位 1.regex類的一些高階話題.首先,我們接著上次的regex的一些繼續 1.1在regex中有乙個方法很奇怪的,那就是它的replace方法,很多的...
核心物件執行緒同步 信標核心物件
信標核心物件用於對資源進行計數。乙個使用數量 乙個是最大資源數量 用於標識信標能夠控制的資源的最大數量 乙個是當前資源數量 用於標識當前可以使用的資源的數量 如果當前資源的數量大於0,則發出信標訊號。如果當前資源數量是0,則不發出信標訊號。系統決不允許當前資源的數量為負值。當前資源數量決不能大於最大...