Windows進程間共享內存通訊實例html
抄抄補補整出來緩存
採用內存映射文件實現WIN32進程間的通信:Windows中的內存映射文件的機制爲咱們高效地操做文件提供了一種途徑,它容許咱們在WIN32進程中保留一段內存區域,把硬盤或頁文件上的目標文件映射到這段虛擬內存中。注意:在程序實現中必須考慮各進程之間的同步問題。
安全
在Windows操做系統下,任何一個進程不容許讀取、寫入或是修改另外一個進程的數據(包括變量、對象和內存分配等),可是在某個進程內建立的文件映射對象的視圖卻可以爲多個其餘進程所映射,這些進程共享的是物理存儲器的同一個頁面。服務器
所以,當一個進程將數據寫入此共享文件映射對象的視圖時,其餘進程能夠當即獲取數據變動狀況。app
爲了進一步提升數據交換的速度,還能夠採用由系統頁文件支持的內存映射文件而直接在內存區域使用,函數
顯然這種共享內存的方式是徹底能夠知足在進程間進行大數據量數據快速傳輸任務要求的。性能
具體實現步驟以下: (http://www.jb51.net/article/52306.htm)大數據
一、在服務器端進程中調用內存映射API函數CreateFileMapping建立一個有名字標識的共享內存;spa
函數CreateFileMapping原型以下:操作系統
二、在建立文件映射對象後,服務器端進程調用MapViewOfFile函數映射到本進程的地址空間內;
三、客戶端進程訪問共享內存對象,須要經過內存對象名調用OpenFileMapping函數,以得到共享內存對象的句柄
四、若是客戶端進程得到共享內存對象的句柄成功,則調用MapViewOfFile函數來映射對象視圖。用戶可使用該對象視圖來進行數據讀寫操做,以達到數據通信的目的。
五、當用戶進程結束使用共享內存後,調用UnmapViewOfFile函數以取消其地址空間內的視圖:
FileMapping用於將存在於磁盤的文件放進一個進程的虛擬地址空間,並在該進程的虛擬地址空間中產生一個區域用於「存放」該文件,這個空間就叫作File View(存放在進程的虛擬內存中),系統並同時產生一個File Mapping Object(存放於物理內存中)用於維持這種映射關係,這樣當多個進程須要讀寫那個文件的數據時,它們的File View其實對應的都是同一個File Mapping Object,這樣作可節省內存和保持數據的同步性,並達到數據共享的目的。
內存映射API函數CreateFileMapping建立一個有名的共享內存:
HANDLE CreateFileMapping(
HANDLE hFile, // 映射文件的句柄,設爲0xFFFFFFFF以建立一個進程間共享的對象
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全屬性
DWORD flProtect, // 保護方式
DWORD dwMaximumSizeHigh, //對象的大小
DWORD dwMaximumSizeLow,
LPCTSTR lpName // 必須爲映射文件命名
);
與虛擬內存相似,保護方式能夠是PAGE_READONLY或是PAGE_READWRITE。若是多進程都對同一共享內存進行寫訪問,則必須保持相互間同步。映射文件還能夠指定PAGE_WRITECOPY標誌,能夠保證其原始數據不會遭到破壞,同時容許其餘進程在必要時自由的操做數據的拷貝。
在建立文件映射對象後使用能夠調用MapViewOfFile函數映射到本進程的地址空間內。
下面說明建立一個名爲MySharedMem的長度爲4096字節的有名映射文件:
HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),
NULL,PAGE_READWRITE,0,0x1000,"MySharedMem");
任何能夠得到的物理文件句柄, 若是你須要建立一個物理文件無關的內存映射也無妨, 將它設置成爲 0xFFFFFFFF(INVALID_HANDLE_VALUE)就能夠了.
並映射緩存區視圖:
LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
其餘進程訪問共享對象,須要得到對象名並調用OpenFileMapping函數。
HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,
FALSE,"MySharedMem");
一旦其餘進程得到映射對象的句柄,能夠象建立進程那樣調用MapViewOfFile函數來映射對象視圖。用戶可使用該對象視圖來進行數據讀寫操做,以達到數據通信的目的。
當用戶進程結束使用共享內存後,調用UnmapViewOfFile函數以取消其地址空間內的視圖:
if (!UnmapViewOfFile(pszMySharedMapView))
{
AfxMessageBox("could not unmap view of file");
}
要將文件中的數據映射到進程的虛擬內存中,你必須建立一個文件的視圖。
MapViewOfFile和MapViewOfFileEx函數使用CreateFileMapping返回的文件映射對象句柄來在進程的虛擬地址空間裏創建文件的視圖,或者文件的某個部分。若是這些函數指定的權限標誌和CreateFileMapping中的權限標誌不一致,則會執行失敗。
MapViewOfFile函數返回一個指向文件視圖的指針。利用MapViewOfFile中聲明的地址指針,程序就能夠從文件中讀以及向文件中寫入數據。向文件視圖中寫入數據會致使文件映射對象改變。真正將數據寫入到磁盤上的文件,由系統負責處理。數據並非立刻就別寫到磁盤上,不少文件的輸入輸出都被緩存起來,以改善系統的性能。程序能夠調用FlushViewOfFile函數來越過這個方式,強迫系統立刻將數據寫入到磁盤中去。
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
寫一個建立共享內存,並寫入數據
-
#ifdef CHAR_TEST
-
char* pData = NULL;
-
#else
-
HWND* pData = NULL;
-
-
#endif // CHAR_TEST
-
-
-
HANDLE hFileMap = NULL;
-
hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T( "WndData"));
-
if (!hFileMap) // 不存在則建立
-
{
-
hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, _T( "WndData"));
-
}
-
-
if (hFileMap != NULL)
-
{
-
#ifdef CHAR_TEST
-
pData = ( char*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
-
#else
-
pData = (HWND*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
-
#endif // CHAR_TEST
-
-
if (pData == NULL)
-
{
-
CloseHandle(hFileMap);
-
hFileMap = NULL;
-
}
-
}
-
-
HANDLE hMutex = CreateMutex( NULL, TRUE, _T( "WndMutex"));
-
-
#ifdef CHAR_TEST
-
char* strValue = "123abcpStr";
-
//pData = strValue;
-
memcpy(pData, strValue, strlen(strValue));
-
-
#else
-
CStatic* pStcPic = (CStatic*)GetDlgItem(IDC_STC_PIC);
-
HWND hWnd = pStcPic->m_hWnd;
-
//pData = &hWnd;
-
memcpy(pData, &hWnd, sizeof(HWND*));
-
#endif // char_te
-
-
-
//FlushViewOfFile(pData, sizeof(HWND*));
-
-
ReleaseMutex(hMutex);
![](http://static.javashuo.com/static/loading.gif)
-----------------------------------------------------------------------------------
讀取共享數據:
-
HANDLE hMutex = NULL;
-
while ( true)
-
{
-
hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T( "WndMutex"));
-
if ( NULL != hMutex)
-
{
-
break;
-
}
-
Sleep( 200);
-
}
-
-
WaitForSingleObject(hMutex, INFINITE);
-
-
HANDLE hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T( "WndData"));
-
ASSERT(hFileMap);
-
-
#if 1
-
HWND* pData = (HWND*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
-
HWND hGet = *pData;
-
#else
-
char* pData = ( char*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 1024);
-
char* strTemp = pData;
-
AfxMessageBox(strTemp);
-
#endif
-
-
HDC dc = ::GetDC(hGet);
-
-
UnmapViewOfFile(pData);
-
-
ReleaseMutex(hMutex);
![](http://static.javashuo.com/static/loading.gif)
在向共享內存寫值的時候,char* strValue = "123abcpStr";
再賦給 pData = strValue; 在讀取的時候會讀不到數據!
必定要用內存烤貝:memcpy(pData, strValue, strlen(strValue));
jpg 改 rar