程序的核心物件控制代碼表

2021-04-20 02:56:53 字數 3522 閱讀 2670

/*

當程序初始化的時候,系統會為其分配乙個控制代碼表。該控制代碼表只用於核心物件。

具體該控制代碼表在系統中是種怎樣的結構和是怎麼被系統管理的,現在沒有說明文件。

程序控制代碼表的大體結構如下:

index

pointer to kernal object memory block

access mask

flags

*//*

建立乙個核心物件

當程序被初始化之後,其控制代碼表是空的。當程序內的一線程通過指定的函式建立了

乙個核心物件時,核心會為物件分配一塊記憶體區域並初始化這塊區域。然後核心

會在程序的控制代碼表中查詢乙個空的入口,找到之後會初始化控制代碼表的以索引定位

的區域。初始化的主要過程就是填充控制代碼表的乙個單元,包括指定核心物件位址,

指定訪問碼,指定標記等。

以下是用於建立核心物件的一些函式:

*/handle createthread(

psecurity_attributes psa,

size_t dwstacksize,

lpthread_start_routine pfnstartaddress,

pvoid pvparam,

dword dwcreationflags,

pdword pdwthreadid);

handle createfile(

pctstr pszfilename,

dword dwdesiredaccess,

dword dwsharemode,

psecurity_attributes psa,

dword dwcreationdisposition,

dword dwflagsandattributes,

handle htemplatefile);

handle hfile,

psecurity_attributes psa,

dword flprotect,

dword dwmaximumsizehigh,

dword dwmaximumsizelow,

pctstr pszname);

handle createsemaphore(

psecurity_attributes psa,

long linitialcount,

long lmaximumcount,

pctstr pszname);

/*所有建立核心物件的函式都會返回乙個與程序相關的控制代碼,該控制代碼可被程序內的

任何執行緒使用。這個控制代碼實際上是可以被4整除的,其結果就是核心物件在控制代碼表

中的索引號,通過應該索引號就可以找到物件資訊在控制代碼表中的位置。所以當你

除錯程式的時候,會發生核心物件的控制代碼都是一些4啦8啦等比較小的整數。

當你呼叫需要以核心物件控制代碼為引數的函式時,你就可以先建立乙個核心物件,

然後將建立函式的返回值傳遞給下乙個需要控制代碼作引數的函式。在內部的實現上,

該函式其實是在程序的核心物件控制代碼表中查詢你想操作的核心物件的位址,然後

會以一種良好的方式操作核心物件的資料結構。

當你傳遞乙個非法的控制代碼時,呼叫的函式會返回錯誤,通過getlasterror會得到

6(error_invalid_handle),因為控制代碼會被當作控制代碼表的索引值,且控制代碼是與程序

關聯在一起的,可以被其它程序使用。如果你曾嘗試著這麼做的話,其結果是你

引用了其它程序的同索引號的核心物件,你不知道你引用的究竟是何物件。

如果你呼叫建立核心的函式失敗時,函式通常會返回0(null),這也就是為什麼

核心物件的第乙個可用控制代碼值是4的原因。系統通常對於這種安全性檢查做得不夠,

不幸的是,有些函式建立失敗時會返回-1,即invalid_handle_value,所以當你

檢查建立核心物件是否成功時一定要小心,不能統一地將函式的返回值與null進行

比較。其實,只要知道一些特殊情況就可以了,當你呼叫createfile時,就要記住

它失敗時會返回-1,所以檢查它是否正確執行時將返回值和invalid_handle_value

比較即可。

兩個錯誤比較的例子如下:

*/handle hmutex = createmutex(…);

if (hmutex == invalid_handle_value) 

handle hfile = createfile(…);

if (hfile == null) 

/*關閉核心物件:

不管你以何種方式建立了乙個核心物件,當你用完它時,你應該通知系統你用完了

通知的方式就是呼叫函式:

*/bool closehandle(handle hobject);

/*在內部機理上,該函式會首先檢查程序的控制代碼表以確認傳遞給它的控制代碼所標記的

核心物件程序確實有訪問它的許可權。如果控制代碼有效,系統會獲取控制代碼所標記的核心

物件的位址並減小使用次數這一資料成員。如果使用次數變成了0,核心物件會

被銷毀並在記憶體中刪除。

如果傳遞給closehandle的是乙個無效控制代碼,此時可能會有兩件事發生。如果你的

程序執行正常,closehandle會返回false,此時getlasterror會返回無效控制代碼的

標識error_invalid_handle;但你的程序此時正在被除錯,系統會丟擲異常

0xc0000008(指定了無效的控制代碼),此時我們就可以根據異常來除錯**了。

在函式closehandle返回之後,程序控制代碼表中被關於的控制代碼會被清除,意思就是說

關閉之後的控制代碼對關閉其的程序無效了,我們不能再嘗試使用它。控制代碼在控制代碼表

中的清除與控制代碼所代表的核心物件的銷毀並無直接關係,即如果控制代碼被清除了,

但其先前所代表的核心物件及可能存在於核心中。關閉控制代碼的意思就是程序已無

訪問控制代碼所代表的核心物件的許可權了。核心物件的存在與否決定於其資料成員--

使用次數。如果使用次數不為0,說明還有其它程序在使用它,此時核心不能銷毀

物件,只有當核心物件的使用次數變成0的時候,核心才會銷毀物件。

注意點:

使用控制代碼同使用指標一樣需要注意很多,多數情況下我們會將核心物件的句

柄關聯到乙個成員變數。當我們呼叫了closehandle之後就宣布了控制代碼的無效,

此時也應該將控制代碼先前關聯的成員變數設定為null,以防不經意再次使用它。

再說一說忘記呼叫closehandle的問題吧,如果忘記通過該函式關閉核心物件的

控制代碼,只能說可能會發生物件洩漏。在程序執行的過程中,可能由於忘記關閉

控制代碼導致物件洩漏,但一旦程序結束後,系統會檢查程序的控制代碼表,如果發現有

未關閉的控制代碼,系統會幫你關閉控制代碼。此時如果控制代碼所代表的核心物件的使用

次數變成0,核心會去銷毀核心物件。這樣就保證不會出現記憶體和資源的洩漏。

由上可知,核心物件的洩漏只能發生在程序執行的過程中,程序結束之後,系統

保證會妥善地清除該程序使用的所有資源。這種機制對所有物件,資源如gdi物件,

記憶體塊都是有效的。當程序結束之後,系統會收回程序使用的所有資源。

*/

程序的核心物件控制代碼表

當乙個程序被初始化時,系統要為它分配乙個控制代碼表。該控制代碼表只用於核心物件,不用於使用者物件或gdi物件。它只是個資料結構的陣列。每個結構都包含乙個指向核心物件的指標 乙個訪問遮蔽和一些標誌。程序的控制代碼結構 索引 核心物件記憶體塊的指標 訪問遮蔽 標誌位的dword 標誌 標誌位的dword...

win32程序概念之控制代碼表,以及核心物件

我們知道.我們使用createprocess 的時候會返回乙個程序控制代碼.以及執行緒控制代碼.其實在呼叫createprocess的時候.核心中會新建乙個eprocess結構來儲存我們的程序資訊.例如如下圖 但是有乙個問題.怎麼給三環使用.難道直接返回eprocess?其實不是這樣的.第一epro...

核心物件與控制代碼的關係

一 乙個物件是不是核心物件,通常可以看建立此物件api的引數中是否需要 psecurity attributes 型別的引數。三 每個程序中有乙個控制代碼表 handle table 這個控制代碼表僅供核心物件使用,如下圖 四 解開此中的秘密 比如呼叫建立乙個執行緒的api handle hthre...