內核對象(3)

         1、內核對象包括:時間對象,文件對象,I/O完成端口對象。作業對象,進程對象,線程對象,互斥對象,信號量對象等,具體的可以通過網址:http://www.microsoft.com/technet/sysinternals/utilities/winobj.mspx獲得內核對象列表查看。

    內核對象都是調用不同名稱的函數來完成的,比如:調用Createthread函數,系統將創建一個線程。每個內核對象都只是一塊內存塊(數據結構),它由操作系統內核分配,且只能操作系統內核訪問。這個內存塊是一個數據結構,其成員維護着與對象相關的信息。(其中少數成員是所有對象都有的,如安全描述和使用計數等)對於,進程對象,其獨有進程ID,一個基本優先級和一個退出代碼;而一個文件對象獨有一個字節偏移量、一個共享模式和打開模式。

    當調用了一個創建內核對象的函數後,會返回一個句柄(handle),它標識了所創建的這個對象。在32bit系統中其爲32位值,64bit系統下,則爲64位值。這些句柄是與進程相關聯的(下面會介紹如何相關聯)。

內核對象有使用計數機制,初次創建時引用計數是1,另一個進程獲得現有內核對象的訪問權後,使用計數會增加,使用該內核對象的進程終止時,會遞減。當使用計數到0時,被銷燬。

        

      2、一個進程在初始化時,系統會分配一個句柄表。(句柄表提供內核對象的使用,不包括用戶對象和GDI對象,比如圖片資源對象等不屬於內核對象)

    句柄表:是一個數據結構數組,每個元素都是一個指針(其指向一個內核對象),一個訪問掩碼和一些標誌。(可以將句柄理解爲此表的索引

進程一開始,句柄表爲空。當在其主線程中,創建一個內核對象後,內核會創建相應的信息,並且放在一塊內存塊中(此時表不爲空了)。返回的句柄,可以由此進程中所有的線程調用。

    調用一個函數時,如WaitForSingleObject函數。其內部會查找進程的句柄表,獲得內核對象的指針,然後用一種恰當的方式處理內核對象的數據結構。傳入無效的handle,會失敗。可以調用GetLastError查看。

    由於handle是作爲表的索引的,所以,handle與進程相關聯。如果在其他進程中引用,那麼其會索引到其他進程的表,會發生錯誤。

    調用CloseHandle函數關閉內核對象。其內部,會先檢查主調進程的句柄表,驗證這個進程“確實有權訪問這個對象”。如果句柄有效,則“使用計數”減1。如果計數成0,內核對象將被銷燬。在函數返回前,會清理進程句柄表中的對應項-------即這個句柄現在是無效的,不要再訪問它了。無論內核對象當前是否銷燬,這個清除都會發生。

    也就是,一點調用了CloseHandle,我們的進程就不能訪問那個內核對象了;但是,如果這個內核對象的“計數“不爲0,則對象不會被銷燬,這是正常的。因爲,它表明只是當前線程或進程對此內核對象不再感興趣,不會再使用,但是可能還有其他的線程或進程在使用該內核對象。當全部的進程和線程都不再感興趣時,此內核對象“使用計數”被遞減爲0,被銷燬。

    另外,進程終止時,所有的內核對象、資源以及內存塊等,都會被釋放掉。

      

      3、跨進程共享內核對象

    1、對象句柄繼承:在進程之間有父子關係時可以使用。步驟如下:(1)父進程創建內核對象時,指定此內核對象的句柄可被繼承的。

SECURITY_ATTRIBUTES sa;
sa.nLength =sizeof(sa);
sa.lpSecurityDescriptor =NULL;
sa.bInheritHandle =TRUE;//指定爲句柄可繼承
HANDLE hMutex=CreateMutex(&sa,FALSE,NULL);
這樣變指定了創建的內核對象的句柄是可被繼承的了。

                                                                                                             (2)父進程創建子進程。調用CreateProcess函數,並將其中的bInHeritHandles參數設置爲TRUE,表明我們希望子進程繼承父進程的“可繼承句柄”。

    2、爲對象命名:當在A進程中調用createmutex創建一個名爲“Jeff”的內核對象後,在B進程(非父子關係也行)中調用createmutex創建“Jeff”時,會先查看內核是否有同名對象,如果存在,則檢查類型,如果類型也相同,(則再執行安全檢查,看其是否有訪問權限),都通過的情況下,系統會在B進程的句柄表中找一個空白記錄項,將其與現有內核對象綁定。如果類型不匹配,或調用者被拒絕訪問,則createmutex函數調用失敗(返回NULL)。如果沒有同名對象,則創建新的內核對象。

也可以調用OpenMutex函數來共享。如果沒有同名,返回NULL。如果同名,類型不同,返回NULL。如果同名,類型同,且允許訪問(通過dwDesiredAccess指定),則綁定且返回。

open*和create*這兩個系列函數唯一的不同是,如果同名對象不存在,create會創建,open會返回NULL。

    3、賦值對象句柄:調用DuplicateHandle函數。簡單的說,就是獲得當前調用進程句柄表的記錄項,然後在另一個進程的表中創建這個記錄項的一個副本。





發佈了40 篇原創文章 · 獲贊 19 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章