1. 程式人生 > >windows作業系統之跨程序邊界共享核心物件

windows作業系統之跨程序邊界共享核心物件

核心物件:用來管理程序,執行緒,檔案等諸多種類的大量資源。

核心物件只是一個記憶體塊,由作業系統分配,並只能由作業系統訪問。

核心物件的控制代碼表(由程序中的所有執行緒訪問):

索引 指向核心物件記憶體塊的指標 訪問掩碼 標誌
1 0xF0000000 0x??????? 0x0000000
核心物件如何被操作呢?Windows提供了大量的API函式用於此功能。

1. 建立核心物件,舉例如下

     CreateFile(PCTSTR PszFIleName, DWORD dwDesiredAccess, DWORD dwShareMode, PSECURITY_ATTRIBUTES psa

, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);//建立檔案核心物件

2. 關閉核心物件,舉例如下

    CloseHandle(HANDLE hobjiect);//作用是將核心物件的使用計數減1,如果為0時,銷燬核心物件,不管是否銷燬,該程序的所有執行緒不能訪問該核心物件。


由於核心物件的具有安全屬性,並且不同程序的核心物件存在於各自程序的地址中,如何跨程序訪問核心物件呢?

三種機制實現上述功能:

一、使用物件控制代碼繼承,舉例如下:

SECURITY_ATTRIBUTES  sa;

sa.nLength = sizeof(sa);

sa.lpSecurityDescriptor = NULL;

sa.bInheritHandle = TRUE;

Handle hMutex = CreateMutex(&sa, FALSE, NULL);

程序控制代碼表的表現如何?當標誌一欄的數值為1時,即代表該核心物件可以被繼承。

索引 指向核心物件記憶體塊的指標 訪問掩碼 標誌
1 0xF0000000 0x??????? 0x0000000
2       0x00000000                           (不可用) (不可用)
1 0xF0000010 0x??????? 0x0000001

如何讓子程序能夠使用父程序的物件控制代碼呢?舉例如下:

Bool CreatePorcess()中將安全描述符的繼承引數設定為TRUE;這樣的作用是什麼呢?

建立子程序後,子程序不會立即執行,而是等待遍歷父程序的程序控制代碼表,將標誌為1即可以繼承的控制代碼複製到子程序的控制代碼表,同時將控制代碼的使用計數加1。

如何將控制代碼值傳遞給子程序呢?

1. 採用命令列的方式。2. 讓父程序等待子程序完成初始化,然後父程序可以將一條訊息傳送到由子程序中的一個執行緒建立的一個視窗。3.父程序向環境快中新增一個環境變數。


二、為物件命名

舉例:CreateMutex(PSECURITY_ATTRIBUTES psa, BOOL bInitialOwner, PCTSTR psaName);

原理如果程序A建立一個命名的核心物件。程序B呼叫Create函式建立同樣名字的核心物件時,系統首先會檢查是否存在該名字的核心物件,如果存在進一步檢查訪問安全性,如果OK就會在程序B中建立程序A同樣的程序控制代碼表。但是由於系統無法保證核心物件名稱的唯一性,為此我們可以採用OpenMutex的方式,如果存在系統會在程序B複製核心物件的控制代碼表,否則返回失敗。


三、複製物件控制代碼

DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, PHANDLE phTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions);

這個函式獲得一個程序的控制代碼表中的一個記錄項,然後在另一個程序的控制代碼表中建立這個記錄項的一個副本。

第一個引數是當前的源程序控制代碼;第二引數是當前的資源控制代碼;第三個是目標程序的控制代碼,

第四個是你要得到的目的控制代碼,這裡應該是一個變數,使用指標,DuplicateHandle函式會將得到的控制代碼設定到這個引數上,

第五個是訪問的方式,

第六個引數是得到的控制代碼能不能被得到的其的程序的子程序繼承。

如果第七個引數是DUPLICATE_SAME_ACCESS flag標誌,那麼這個引數將被忽略,

1. DuplicateHandle獲得一個程序控制代碼表中的一個記錄項,然後在另一個程序的控制代碼表中建立這個記錄項的一個副本。
2. DuplicateHandle 中dwOptions引數可以指定DUPLICATE_SAME_ACCESS和DUPLICATE_CLOSE_SOURCE標誌。如果指定DUPLICATE_SAME_ACCESS標誌將希望目標控制代碼擁有與源程序的控制代碼一樣的訪問掩碼。如果指定DUPLICATE_CLOSE_SOURCE標誌,會關閉源程序的控制代碼。使用這個標誌,核心物件計數不會受到影響。
3. DuplicateHandle 函式與繼承一樣,目標程序並不知道它現在能訪問一個新的核心物件,所以源程序以某種方式通知目標程序。與繼承不一樣的是,源程序不能使用命令列引數或更改目標程序的環境變數。
4. 可以利用DuplicateHandle修改核心物件的訪問許可權
5.絕對不能使用CloseHandle函式關閉通過phTargetHandle引數返回的控制代碼。