標籤:虛擬 oca 之間 .cpp erro api 高效 app 內容
0x01 使用檔案對應實現共用記憶體。
用記憶體對應檔實現進程間的通訊:Windows中的記憶體對應檔的機製為我們高效地操作檔案提供了一種途徑,它允許我們在進程中保留一段記憶體地區,把硬碟或頁檔案上的目標檔案映射到這段虛擬記憶體中。注意:在程式實現中必須考慮各進程之間的同步問題。
FileMapping用於將存在於磁碟的檔案放進一個進程的虛擬位址空間,並在該進程的虛擬位址空間中產生一個地區用於“存放”該檔案,這個空間就叫做File View(存放在進程的虛擬記憶體中),系統並同時產生一個File Mapping Object(存放於實體記憶體中)用於維持這種映射關係,這樣當多個進程需要讀寫那個檔案的資料時,它們的File View其實對應的都是同一個File Mapping Object,這樣做可節省記憶體和保持資料的同步性,並達到資料共用的目的。
0x02 細節
1)物理檔案控制代碼
任何可以獲得的物理檔案控制代碼,如果需要建立一個物理檔案無關的記憶體映射也無妨,將它設定成為 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.
如果需要和物理檔案關聯,要確保你的物理檔案建立的時候的訪問模式和"保護設定"匹配,比如:物理檔案唯讀,記憶體映射需要讀寫就會發生錯誤。推薦你的物理檔案使用獨佔方式建立。
如果使用 INVALID_HANDLE_VALUE,也需要設定需要申請的記憶體空間的大小,無論物理檔案控制代碼參數是否有效,這樣 CreateFileMapping就可以建立一個和物理檔案大小無關的記憶體空間,甚至超過實際檔案大小,如果物理檔案有效,而大小參數為0,則返回給你的是一個和物理檔案大小一樣的記憶體空間位址範圍。返回給你的檔案對應地址空間是可以通過複製,整合或者命名得到,初始內容為0。
2)保護設定
就是安全設定,不過一般設定NULL就可以了,使用預設的安全配置. 在win2k下如果需要進行限制,這是針對那些將記憶體檔案對應共用給整個網路上面的應用進程使用是,可以考慮進行限制.
3)高位檔案大小
32位地址空間,設定為0。
4) 共用記憶體名稱
命名可以包含 "Global"或者 "Local" 首碼在全域或者會話名空間初級檔案對應.其他部分可以包含任何除了()以外的字元,可以參考 Kernel Object Name Spaces.
5)調用CreateFileMapping的時候GetLastError的對應錯誤
ERROR_FILE_INVALID 如果企圖建立一個零長度的檔案對應,應有此報
ERROR_INVALID_HANDLE 如果發現你的命名記憶體空間和現有的記憶體映射,互斥量,訊號量,臨界區同名就麻煩了
ERROR_ALREADY_EXISTS 表示記憶體空間命名已經存在
使用函數CreateFileMapping建立一個想共用的檔案資料控制代碼,然後使用MapViewOfFile來擷取共用的記憶體位址,然後使用OpenFileMapping函數在另一個進程裡開啟共用檔案的名稱,這樣就可以實現不同的進程共用資料。
0x03 API
1.記憶體映射API函數CreateFileMapping建立一個有名字標識的共用記憶體
WINBASEAPI_Ret_maybenull_HANDLEWINAPICreateFileMappingW( _In_ HANDLE hFile, // 對應檔的控制代碼,若設為0xFFFFFFFF(即:INVALID_HANDLE_VALUE)則建立一個進程間共用的對象,(即建立了一個和物理檔案大小無關的記憶體空間) _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, //安全屬性 _In_ DWORD flProtect, //保護方式 _In_ DWORD dwMaximumSizeHigh, //對象的大小 _In_ DWORD dwMaximumSizeLow, _In_opt_ LPCWSTR lpName //對應檔名,即共用記憶體的名稱 );
與虛擬記憶體類似,保護方式參數可以是PAGE_READONLY或是PAGE_READWRITE。如果多進程都對同一共用記憶體進行寫訪問,則必須保持相互間同步。對應檔還可以指定PAGE_WRITECOPY標誌,可以保證其未經處理資料不會遭到破壞,同時允許其他進程在必要時自由的操作資料的拷貝。
MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"劉大大別是妖怪吧");
2.在建立檔案對應物件後,伺服器端進程調用MapViewOfFile函數映射到本進程的地址空間內
BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
3、用戶端進程訪問共用記憶體對象,需要通過記憶體對象名調用OpenFileMapping函數,以獲得共用記憶體對象的控制代碼
MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"劉大大別是妖怪吧");
4、如果用戶端進程獲得共用記憶體對象的控制代碼成功,則調用MapViewOfFile函數來映射物件檢視。使用者可以使用該物件檢視來進行資料讀寫操作,以達到資料通訊的目的。
例:映射緩衝區視圖
BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
5、當使用者進程結束使用共用記憶體後,調用UnmapViewOfFile函數以取消其地址空間內的視圖:
if (BaseAddress){ UnmapViewOfFile(BaseAddress); SharedMapView=NULL;}
原始碼:
1 // Server.cpp : 定義控制台應用程式的進入點。 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 7 int main() 8 { 9 10 HANDLE MappingHandle = NULL;11 PVOID BaseAddress = NULL;12 //建立一個物理檔案無關的記憶體映射13 //建立了一個和物理檔案大小無關的記憶體空間14 MappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,0x1000, L"劉大大別是妖怪吧");15 16 if (MappingHandle==NULL)17 {18 return 0;19 }20 21 BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);22 23 24 __try25 {26 memcpy(BaseAddress, "HelloClient", strlen("HelloClient")+1);27 28 printf("Input AnyKey To Continue\r\n");29 getchar();30 31 printf("%s\r\n", BaseAddress);32 }33 __except (EXCEPTION_EXECUTE_HANDLER)34 {35 printf("異常\r\n");36 goto Exit;37 }38 39 40 41 42 Exit:43 if (MappingHandle!=NULL)44 {45 CloseHandle(MappingHandle);46 MappingHandle = NULL;47 }48 49 printf("Input AnyKey To Exit\r\n");50 getchar();51 return 0;52 }
Server.cpp
1 // Client.cpp : 定義控制台應用程式的進入點。 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 7 int main() 8 { 9 HANDLE MappingHandle = NULL;10 PVOID BaseAddress = NULL;11 12 MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"劉大大別是妖怪吧");13 14 if (MappingHandle==NULL)15 {16 return 0;17 }18 BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);19 __try20 {21 printf("%s\r\n", BaseAddress); 22 memcpy(BaseAddress, "HelloServer", strlen("HelloServer") + 1);23 24 }25 __except (EXCEPTION_EXECUTE_HANDLER)26 {27 printf("異常\r\n");28 goto Exit;29 }30 31 Exit:32 33 if (MappingHandle!=NULL)34 {35 CloseHandle(MappingHandle);36 MappingHandle = NULL;37 }38 printf("Input AnyKey To Exit\r\n");39 getchar();40 return 0;41 }
View Code
windows檔案對應