標籤:windows 核心對象 核心對象共用
1核心對象定義:
1.1:每個內 核對象只是核心分配的一個記憶體塊,並且只能由該核心訪問。
1.2:該記憶體塊是一種資料結構,它的成員負責維護該對象的各種資訊。
有些資料成員(如安全性描述符、使用計數等)在所有物件類型中是相同的,但大多數資料成員屬於特定的物件類型。例如,進程對象有一個進程ID 、一個基 本優先順序和一個結束代碼,而檔案對象則擁有一個位元組位移、一個共用模式和一個開啟模式。
2核心對象種類:
比如存取符號對象、 事件對象、檔案對象、檔案對應物件、I / O 完成連接埠對象、工作物件、信箱對象、互斥對象、管道對象、進程對象、信標對象、線程對象和等待計 時器對象等。
3核心對象擁有者:
核心對象由核心所擁有,而不是由進程所擁有。如果你的進程調用了一個建立核心對象的函數,然後你的進程終止運行,那麼核心對象不 一定被撤消。在大多數情況下,對象將被撤消,但是如果另一個進程正在使用你的進程建立的核心對象,那麼該核心知道,在另一個進程停止使用該 對象前不要撤消該對象,必須記住的是,核心對象的存在時間可以比建立該對象的進程長。
4核心對象使用計數:
核心對象悲哀建立時候,計數設定為1,當有進程訪問該核心對象的時候,計數加1,當進程終止啟動並執行時候,核心會判斷該對象技術是否為0,是0的話就撤銷該核心對象。
5進程對象核心控制代碼表:
當一個進程被初始化時,系統要為它分配一個控制代碼表。該控制代碼表只用於核心對象,不用於使用者物件或G D I 對象。
當進程初次被初始化時,它的控制代碼表是空的。然後,當進程中的線程調用建立核心對象的函數時,比如Cr e a t e F i l e M a p p i n g ,核心 就為該對象分配一個記憶體塊,並對它初始化。
用於建立核心對象的所有函數均返回與進程相關的控制代碼,這些控制代碼可以被在相同進程中啟動並執行任何或所有線程成功地加以使用。
6核心對象的關閉和撤銷的區別:
核心對象的關閉是指一個進程利用CloseHandle(Handle hObj)函數把核心對象在該進程中的控制代碼表中清除掉,因而該進程不能再訪問該核心對象。
核心對象的撤銷試著核心把核心對象從記憶體中清除,此時的核心對象計數為0.
兩者的區別:核心對象關閉是進程操作的,關閉核心對象不一定會撤銷對象;撤銷對象是核心操作的,當撤銷對象的時候,對象一定會關閉的。
7 共用核心對象
7.1 通過物件控點的繼承性
只有當進程具有父子關係時,才能使用物件控點的繼承性。在這種情況下,父進程可以使用一個或多個核心物件控點,並且該父進程可以決定產生一 個子進程,為子進程賦予對父進程的核心對象的訪問權。
實施步驟:
7.1.1:父進程必須指定一個S E C U R I T Y _ AT T R I B U TE S 結構並對它進行初始化,然後將該結構的地址傳遞給特定的Cr e a t e 函數。
SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecuntyDescriptor = NULL; /Make the returned handle inheritable. sa.bInheritHandle =- TRUE; HANDLE hMutex = CreateMutex(&sa,FALSE, NULL);
7.1.2:父進程產生子進程
BOOL CreateProcess( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURITY_ATTRIBUTES psaProcess, PSECURITY_ATTRIBUTES psaThread, BOOL bInheritHandles, DWORD fdwCreale, PVOIO pvEnvironment, PCTSTR pszCurDir, PSTARTUPINFO psiStartInfo, PPROCESS_INFORMATION ppiProcInfo);
要把bInheritHandles設定為True,表示是繼承了父進程。
7.1.3子進程確定繼承核心對象的方法
子進程為了確定它期望的核心對象的控制代碼值,最常用的方法是將控制代碼值作為一個命令列參數傳遞給子進程。
7.1.3 改變控制代碼標誌
當父父進程想選擇不同的子進程具有不同的控制代碼繼承權的時候,可以通過設定控制代碼的標誌來實現。通過該函數來實現設定控制代碼的標誌
BOOL SetHandleInformation( HANDLE hObject, DWORD dwMask, //標誌位 DWORD dwFlags); //標識值
7.2 命名物件
7.2.1建立命名核心對象
HANDLE CreateJobObject(
PSECURITY_ATTRIBUTES psa,
PCTSTR pszName);
通過觀察建立核心對象的函數,我們知道其中的最後一個參數是一個字串,這個字串表示核心對象的名字。當然如果我們不想給它起名字的話,我們可以設定其為NULL。該名字的長度最多可以達到MAX_PATH(定義為260 )個字元。
HANDLE hMutexPronessA = CreateMutex(NULL, FALSE,"JeffMutex");HANDLE hMutexProcessB = CreateMutex(NULL, FALSE,"JeffMutex");
此時第一次調用該函數時候,建立一個名字為JeffMutex的核心對象,第二次調用該建立核心對象函數時候,由於待建立的核心對象的名字以及類型都一樣,再加上如果許可權符合的話,此時在進程B中就不會再次建立核心對象,而是引用了進程A中同名同類型的對象JeffMutex。同時核心對象的計數就會加1.
警告:如果命名的核心對象已經存在,那麼再次建立該名字的核心對象的時候,將會忽略第二次建立時傳遞給函數的參數並且不再建立此核心對象,否則會建立一個按照第二次指定參數的新的核心對象。
7.2.2 開啟命名核心對象
可以利用Open函數來開啟已經有的命名核心對象,而不是去用Create***來實現。兩個的區別是:當沒有該核心對象的時候,Open函數會運行失敗,而Create***函數則會建立一個新的核心對象。例如:
HANDLE OpenFileMapping( DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);
7.3 複製進程
把進程A中的某個核心對象的控制代碼複製到進程B 中的控制代碼表中。
BOOL DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLEhTargetProcessHandle, PHANDLE phTargetHandle, DWORD dwDesiredAccess, //訪問屏蔽值 BOOL bInheritHandle, //繼承標誌 DWORD dwOptions); //是否繼承源進程的訪問屏蔽值
複製核心對象的一個執行個體
從例子中可以看到同一個進程的控制代碼表中可以有兩個控制代碼,它們欲訪問的核心對象值相同,但是一些訪問標誌以及繼承許可權可以不同。
#include <windows.h>DWORD CALLBACK ThreadProc(PVOID pvParam);int main(){ HANDLE hMutex = CreateMutex(NULL, FALSE, NULL); HANDLE hMutexDup, hThread; DWORD dwThreadId; DuplicateHandle(GetCurrentProcess(), hMutex, GetCurrentProcess(), &hMutexDup, 0, FALSE, DUPLICATE_SAME_ACCESS); hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID) hMutexDup, 0, &dwThreadId); // Perform work here, closing the handle when finished with the // mutex. If the reference count is zero, the object is destroyed. CloseHandle(hMutex); // Wait for the worker thread to terminate and clean up. WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); return 0;}DWORD CALLBACK ThreadProc(PVOID pvParam){ HANDLE hMutex = (HANDLE)pvParam; // Perform work here, closing the handle when finished with the // mutex. If the reference count is zero, the object is destroyed. CloseHandle(hMutex); return 0;}