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





