1、進程核心物件控點表
2、建立與關閉核心對象
3、進程間核心物件控點的共用
1、進程核心物件控點表
當一個進程初始化時,系統會為它分配一張核心物件控點表。這個表只用於管理核心物件控點。GDI和使用者物件不會影響到這張表。表中的每一項有4個域。 即控制代碼ID,對象記憶體位址,訪問屏蔽位,標誌位。
當一個進程初始化時,控制代碼表為空白。 現在假設你調用CreateFile函數建立一個檔案對象,核心首先會尋找當前進程中的控制代碼表,將一個空的表項取出來,並分配一個核心對象,將該對象的地址寫入第二個域(即,對象記憶體位址),然後訪問屏蔽設定為完全訪問,相應的標誌位也會被設定。用於核心對象建立時返回與進程相關的控制代碼,而這些控制代碼可以在同一個進程中被其所有線程使用。該控制代碼是一個非透明值,有可能返回的是控制代碼表中的索引,也有可能是一個其它的值。但這個控制代碼的確是可以與這個核心對象相關聯。
2、建立與關閉核心對象
如果建立核心對象失敗,那返回的控制代碼通常為NULL,但也有可能是INVALID_HANDLE_VALUE,例如CreateFile函數。當查看一個函數的傳回值時,應該特別小心。
無論你是怎麼建立核心對象,都應該調用CloseHandle將其釋放。核心會檢測這個對象的引用計數,當發現他的引用計數為0的時候,便會將其釋放。 並且,如果一個進程中,如果調用了CloseHandle,則這個HANDLE對此進程則會變成無效,而對於其它使用這個核心的進程來說,並沒有影響。
3、進程間核心物件控點的共用
當一個進程建立出一個核心對象時,這個對象就與此進程相關聯。但是,並不是所有情況都是如此,許多時候,我們需要多個進程之間共用核心對象。共用一個核心物件控點的方法大概有三種。 1、通過繼承共用,2、通過有名核心對象共用。3、通過控制代碼拷貝共用。
註:共用的是核心對象的控制代碼,核心對象屬於核心,無法共用。
通過繼承共用則要求共用的進程間是父子關係。 如一個進程中調用CreateFile建立了一個檔案對象。如果我們想要這個對象的控制代碼在這個進程的子進程中被使用。則我們在建立這個對象時,對SECURYTY_ATTRIBUTES結構中的bInheritHande設定為TRUE。 這樣這個控制代碼就能夠被子進程共用。 而我們在建立子進程時,需在調用CreateProcess時將其參數bInheritHandles傳遞為TRUE,標誌著他需要繼承父進程的控制代碼。
值得注意的是,繼承控制代碼相當於是對父進程中控制代碼的拷貝,當一個進程被建立時,如果指定為需要對父進程中的控制代碼進行繼承,則系統會尋找其父進程中的控制代碼表,找到可以繼承的控制代碼,並將其整個表項複製到子進程的控制代碼表中。核心對象的引用計數相應增加1。 因此,如果一個子進程被建立後。父進程又建立了一個可以繼承的物件控點。但這個控制代碼不會被子進程繼承。
另外一個問題就是,子進程無法知道自己擁有了該控制代碼的使用權,此時就需要通過一些手法來讓子進程知道。最常用的便是通過參數傳遞。將控制代碼值通過pCommandLine傳遞給子進程,子進程解析後使用。也可以通過訊息或是環境變數的方式通知。。
通過有名對象進行物件控點共用是最簡單的方式,像事件,訊號量,互斥變數等都支援有名建立。如建立CreateMutex的時候,只需為其最後一個參數傳遞一個0結尾的字串,便可以標誌這個變數。需要注意的是,這個名字很有可能衝突,不同種內的核心對象共同使用一個名字池,如果已經有這個名字,並且先前使用此名字的核心對象也是一個Mutex,則當調用GetLastError()時,會返回ERROR_ALREADY_EXISTS。 系統將直接返回其控制代碼,並將其引用計數加1。否則返回NULL,表示建立失敗。
由於這個特性,我們可以使用它來強制你的程式只能開一個執行個體。代碼如下
#include<windows.h><br />#include<tchar.h><br />int _tmain() </p><p>{ </p><p> HANDLE hMutex = CreateMutex(NULL,TRUE,”MyMutex”); </p><p> if(GetLastError() == ERROR_ALREADY_EXISTS) </p><p> { </p><p> MessageBox(TEXT(“程式已經有一個執行個體在執行”),TEXT(“友情提示”),MB_OK);<br /> CloseHandle(hMutex);</p><p> return 0;<br /> } </p><p> //做你程式應該做的事<br /> CloseHandle(hMutex);<br /> return 0; </p><p>} </p><p>本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/wqjqepr/archive/2010/06/26/5695561.aspx
最後一個共用變數的方式就是採用DuplicateHandle進行拷貝,具體用法參照MSDN即可。
對象的控制代碼是一個非透明的值,在不同的場合,會有不同的控制代碼與同一個核心對象對應。標誌著不同的許可權,不同的環境。 因此用到的時候要十分小心。並且應該注意控制代碼的關閉,以防止運行過程中內在泄漏。同時應該注意控制代碼值的有效性,不要使用一個已經釋放了的控制代碼值。