內(nèi)核對象
無論怎樣創(chuàng)建內(nèi)核對象,都要向系統(tǒng)指明將通過調(diào)用C l o s e H a n d l e 來結(jié)束對該對象的操作:
BOOL CloseHandle(HANDLE hobj);
該函數(shù)首先檢查調(diào)用進程的句柄表,以確保傳遞給它的索引(句柄)用于標識一個進程實際上無權訪問的對象。如果該索引是有效的,那么系統(tǒng)就可 以獲得內(nèi)核對象的數(shù)據(jù)結(jié)構的地址,并可確定該結(jié)構中的使用計數(shù)的數(shù)據(jù)成員。如果使用計數(shù)是0 ,該內(nèi)核便從內(nèi)存中撤消該內(nèi)核對象。
如果將一個無效句柄傳遞給C l o s e H a n d l e ,將會出現(xiàn)兩種情況之一。如果進程運行正常,C l o s e H a n d l e 返回FA L S E ,而G e t L a s t E r r o r 則返回E R R O R _ I N VA L I D _ H A N D L E 。如果進程正在排除錯誤,系統(tǒng)將通知調(diào)試程序,以便能排除它的錯誤。
在C l o s e H a n d l e 返回之前,它會清除進程的句柄表中的項目,該句柄現(xiàn)在對你的進程已經(jīng)無效,不應該試圖使用它。無論內(nèi)核對象是否已 經(jīng)撤消,都會發(fā)生清除操作。當調(diào)用C l o s e H a n d l e 函數(shù)之后,將不再擁有對內(nèi)核對象的訪問權,不過,如果該對象的使用計數(shù)沒有遞減為 0 ,那么該對象尚未被撤消。這沒有問題,它只是意味著一個或多個其他進程正在使用該對象。當其他進程停止使用該對象時(通過調(diào)用C l o s e H a n d l e ),該對象將被撤消。
假如忘記調(diào)用C l o s e H a n d l e 函數(shù),那么會不會出現(xiàn)內(nèi)存泄漏呢?答案是可能的,但是也不一定。在進程運行時,進程有可能泄漏資源(如 內(nèi)核對象)。但是,當進程終止運行時,操作系統(tǒng)能夠確保該進程使用的任何資源或全部資源均被釋放,這是有保證的。對于內(nèi)核對象來說,系統(tǒng)將 執(zhí)行下列操作:當進程終止運行時,系統(tǒng)會自動掃描進程的句柄表。如果該表擁有任何無效項目(即在終止進程運行前沒有關閉的對象),系統(tǒng)將關 閉這些對象句柄。如果這些對象中的任何對象的使用計數(shù)降為0 ,那么內(nèi)核便撤消該對象。
因此,應用程序在運行時有可能泄漏內(nèi)核對象,但是當進程終止運行時,系統(tǒng)將能確保所有內(nèi)容均被正確地清除。另外,這個情況適用于所有對象、 資源和內(nèi)存塊,也就是說,當進程終止運行時,系統(tǒng)將保證進程不會留下任何對象。
?
?
?
共享跨越進程邊界的內(nèi)核對象的第二種方法是給對象命名。許多(雖然不是全部)內(nèi)核對象都是可以命名的。例如,下面的所有函數(shù)都可以創(chuàng)建命名的內(nèi)核對象:
HANDLE CreateMutex(
?? PSLCURITY_ATTRIBUTES psa,
?? BOOL bInitialOwner,
?? PCTSTR pszName);
?
HANDLE CreateEvent(
?? PSECURITY_ATTRIBUTES psa,
?? BOOL bManualReset,
?? BOOL bInitialState,
?? PCTSTR pszName);
?
HANDLE CreateSemaphore(
?? PSECURITY_ATTRIBUTES psa,
?? LONG lInitialCount,
?? LONG lMaximumCount,
?? PCTSTR pszNarne);
?
HANDLE CreateWaitableTimer(
?? PSLCURITY_ATTRIBUTES psa,
?? BOOL bManualReset,
?? PCTSTR pszName);
?
HANDLE CreateFileMapping(
?? HANDLE hFile,
?? PSECURITY_ATTRIBUTES psa,
?? DWORD flProtect,
?? DWORD dwMaximumSizeHigh,
?? DWORD dwMaximumSizeLow,
?? PCTSTR pszName);
?
HANDLE CreateJobObject(
?? PSECURITY_ATTRIBUTES psa,
?? PCTSTR pszName);
所有這些函數(shù)都有一個共同的最后參數(shù)p s z N a m e 。當為該參數(shù)傳遞N U L L 時,就向系統(tǒng)指明了想創(chuàng)建一個未命名的(匿名)內(nèi)核對象。當創(chuàng)建一個未命名的對象時,可以通過使用繼承性(如上一節(jié)介紹的那樣)或D u p l i c a t e H a n d l e (下一節(jié)將要介紹)共享跨越進程的對象。若要按名字共享對象,必須為對象賦予一個名字。
如果沒有為p s z N a m e 參數(shù)傳遞M U L L ,應該傳遞一個以0 結(jié)尾的字符串名字的地址。該名字的長度最多可以達到M A X _ PAT H (定義為2 6 0 )個字符。但是,M i c r o s o f t 沒有提供為內(nèi)核對象賦予名字的指導原則。例如,如果試圖創(chuàng)建一個稱為“J e ff O b j ”的對象,那么不能保證系統(tǒng)中不存在一個名字為“J e ff O b j ”的對象。更為糟糕的是,所有這些對象都共享單個名空間。由于這個原因,對下面這個C r e a t e S e m a p h o r e 函數(shù)的調(diào)用將總是返回N U L L :
?