最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

win32下進程間通信(共享內存)實例分析

 更新時間:2014年07月17日 17:22:32   投稿:shichen2014  
這篇文章主要介紹了win32下進程間通信(共享內存)實例分析,對win32應用程序及進程的原理做了較為深入的剖析,需要的朋友可以參考下

一、概述

很多情況下在Windows程序中,各個進程之間往往需要交換數(shù)據(jù),進行數(shù)據(jù)通訊。WIN32 API提供了許多函數(shù)使我們能夠方便高效的進行進程間的通訊,通過這些函數(shù)我們可以控制不同進程間的數(shù)據(jù)交換。

進程間通訊(即:同機通訊)和數(shù)據(jù)交換有多種方式:消息、共享內存、匿名(命名)管道、郵槽、Windows套接字等多種技術?!肮蚕韮却妗保╯hared memory)可以定義為對一個以上的進程是可見的內存或存在于多個進程的虛擬地址空間。例如:如果兩個進程使用相同的DLL,只把DLL的代碼頁裝入內存一次,其他所有映射這個DLL的進程只要共享這些代碼頁就可以了;利用消息機制實現(xiàn)IPC雖然有交換的數(shù)據(jù)量小、攜帶的信息少等缺點,但由于其實現(xiàn)方便、應用靈活而廣泛應用于無須大量、頻繁數(shù)據(jù)交換的內部進程通訊系統(tǒng)之中。

二、同機進程間共享內存的實現(xiàn)

采用內存映射文件實現(xiàn)WIN32進程間的通訊:Windows中的內存映射文件的機制為我們高效地操作文件提供了一種途徑,它允許我們在WIN32進程中保留一段內存區(qū)域,把硬盤或頁文件上的目標文件映射到這段虛擬內存中。注意:在程序實現(xiàn)中必須考慮各進程之間的同步問題。

具體實現(xiàn)步驟如下:

1、在服務器端進程中調用內存映射API函數(shù)CreateFileMapping創(chuàng)建一個有名字標識的共享內存;

函數(shù)CreateFileMapping原型如下:

HANDLE CreateFileMapping (
HANDLE hFile, // 映射文件的句柄,若設為0xFFFFFFFF(即:INVALID_HANDLE_VALUE)則創(chuàng)建一個進程間共享的對象
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, //安全屬性
DWORD flProtect, //保護方式
DWORD dwMaximumSizeHigh, //對象的大小
DWORD dwMaximumSizeLow, 
LPCTSTR lpName // 映射文件名,即共享內存的名稱
);

與虛擬內存類似,保護方式參數(shù)可以是PAGE_READONLY或是PAGE_READWRITE。如果多進程都對同一共享內存進行寫訪問,則必須保持相互間同步。映射文件還可以指定PAGE_WRITECOPY標志,可以保證其原始數(shù)據(jù)不會遭到破壞,同時允許其他進程在必要時自由的操作數(shù)據(jù)的拷貝。

例如:創(chuàng)建一個名為“zzj”的長度為4096字節(jié)的有名映射文件:

HANDLE m_hMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x1000," zzj");

2、在創(chuàng)建文件映射對象后,服務器端進程調用MapViewOfFile函數(shù)映射到本進程的地址空間內;
例:映射緩存區(qū)視圖

void* m_pBaseMapFile=MapViewOfFile(m_hMapFile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

3、客戶端進程訪問共享內存對象,需要通過內存對象名調用OpenFileMapping函數(shù),以獲得共享內存對象的句柄

HANDLE m_hMapFile =OpenFileMapping(FILE_MAP_WRITE,FALSE," zzj"); 

4、如果客戶端進程獲得共享內存對象的句柄成功,則調用MapViewOfFile函數(shù)來映射對象視圖。用戶可以使用該對象視圖來進行數(shù)據(jù)讀寫操作,以達到數(shù)據(jù)通訊的目的。
例:映射緩存區(qū)視圖

void* m_pBaseMapFile=MapViewOfFile(m_hMapFile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

5、當用戶進程結束使用共享內存后,調用UnmapViewOfFile函數(shù)以取消其地址空間內的視圖:

if (m_pBaseMapFile) 
{ 
  UnmapViewOfFile(m_pBaseMapFile); 
  SharedMapView=NULL; 
}

三、使用文件映射實現(xiàn)共享內存。

FileMapping用于將存在于磁盤的文件放進一個進程的虛擬地址空間,并在該進程的虛擬地址空間中產(chǎn)生一個區(qū)域用于“存放”該文件,這個空間就叫做File View(存放在進程的虛擬內存中),系統(tǒng)并同時產(chǎn)生一個File Mapping Object(存放于物理內存中)用于維持這種映射關系,這樣當多個進程需要讀寫那個文件的數(shù)據(jù)時,它們的File View其實對應的都是同一個File Mapping Object,這樣做可節(jié)省內存和保持數(shù)據(jù)的同步性,并達到數(shù)據(jù)共享的目的。

當然在一個應用向文件中寫入數(shù)據(jù)時,其它進程不應該去讀取這個正在寫入的數(shù)據(jù)。這就需要進行一些同步的操作。下邊來看一下具體的API。

CreateFileMaping的用法:

HANDLE CreateFileMapping( //返回FileMapping Object的句柄
HANDLE hFile, //想要產(chǎn)生映射的文件的句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全屬性(只對NT和2000生效)
DWORD flProtect, //保護標致
DWORD dwMaximumSizeHigh, //在DWORD的高位中存放
File Mapping Object //的大小
DWORD dwMaximumSizeLow, //在DWORD的低位中存放
File Mapping Object //的大?。ㄍǔ_@兩個參數(shù)有一個為0)
LPCTSTR lpName //File Mapping Object的名稱。
);

1)物理文件句柄

任何可以獲得的物理文件句柄,如果你需要創(chuàng)建一個物理文件無關的內存映射也無妨,將它設置成為 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

如果需要和物理文件關聯(lián),要確保你的物理文件創(chuàng)建的時候的訪問模式和"保護設置"匹配,比如:物理文件只讀,內存映射需要讀寫就會發(fā)生錯誤。推薦你的物理文件使用獨占方式創(chuàng)建。

如果使用 INVALID_HANDLE_VALUE,也需要設置需要申請的內存空間的大小,無論物理文件句柄參數(shù)是否有效,這樣 CreateFileMapping就可以創(chuàng)建一個和物理文件大小無關的內存空間給你,甚至超過實際文件大小,如果你的物理文件有效,而大小參數(shù)為0,則返回給你的是一個和物理文件大小一樣的內存空間地址范圍。返回給你的文件映射地址空間是可以通過復制,集成或者命名得到,初始內容為0。

2)保護設置

就是安全設置,不過一般設置NULL就可以了,使用默認的安全配置. 在win2k下如果需要進行限制,這是針對那些將內存文件映射共享給整個網(wǎng)絡上面的應用進程使用是,可以考慮進行限制.

3)高位文件大小

32位地址空間,設置為0。

4) 共享內存名稱

命名可以包含 "Global"或者 "Local" 前綴在全局或者會話名空間初級文件映射.其他部分可以包含任何除了()以外的字符,可以參考 Kernel Object Name Spaces.

5)調用CreateFileMapping的時候GetLastError的對應錯誤

ERROR_FILE_INVALID 如果企圖創(chuàng)建一個零長度的文件映射,應有此報
ERROR_INVALID_HANDLE 如果發(fā)現(xiàn)你的命名內存空間和現(xiàn)有的內存映射,互斥量,信號量,臨界區(qū)同名就麻煩了
ERROR_ALREADY_EXISTS 表示內存空間命名已經(jīng)存在

使用函數(shù)CreateFileMapping創(chuàng)建一個想共享的文件數(shù)據(jù)句柄,然后使用MapViewOfFile來獲取共享的內存地址,然后使用OpenFileMapping函數(shù)在另一個進程里打開共享文件的名稱,這樣就可以實現(xiàn)不同的進程共享數(shù)據(jù)。

代碼示例:這個程序包括一個客戶端和一個服務端,服務端創(chuàng)建共享內存,客戶端打開共享內存,兩者通過兩個事件互斥訪問共享內存,實現(xiàn)一個小功能,就是服務端進程從控制臺讀入數(shù)據(jù)發(fā)送給客戶端進程。

服務端:

#include "stdafx.h" 
#include <Windows.h> 
#include <iostream> 
using namespace std; 
 
int main() 
{ 
  HANDLE hMutex      = NULL; 
  HANDLE hFileMapping   = NULL; 
  LPVOID lpShareMemory  = NULL; 
  HANDLE hServerWriteOver = NULL; 
  HANDLE hClientReadOver = NULL; 
 
  //create share memory 
  hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, 
    NULL, 
    PAGE_READWRITE, 
    0, 
    1024*1024, 
    L"ShareMemoryTest"); 
  if (NULL == hFileMapping) 
  { 
    cout << "CreateFileMapping fail:" << GetLastError() << endl; 
    goto SERVER_SHARE_MEMORY_END; 
  } 
 
  lpShareMemory = MapViewOfFile(hFileMapping, 
    FILE_MAP_ALL_ACCESS, 
    0, 
    0,   //memory start address 
    0);   //all memory space 
  if (NULL == lpShareMemory) 
  { 
    cout << "MapViewOfFile" << GetLastError() << endl; 
    goto SERVER_SHARE_MEMORY_END; 
  } 
 
  hMutex = CreateMutex(NULL, FALSE, L"SM_Mutex"); 
  if (NULL == hMutex || ERROR_ALREADY_EXISTS == GetLastError()) 
  { 
    cout << "CreateMutex" << GetLastError() << endl; 
    goto SERVER_SHARE_MEMORY_END; 
  }//多個線程互斥訪問 
 
  //send data 
  hServerWriteOver = CreateEvent(NULL, 
    TRUE, 
    FALSE, 
    L"ServerWriteOver"); 
  hClientReadOver = CreateEvent(NULL, 
    TRUE, 
    FALSE, 
    L"ClientReadOver"); 
  if (NULL == hServerWriteOver || 
    NULL == hClientReadOver) 
  { 
    cout << "CreateEvent" << GetLastError() << endl; 
    goto SERVER_SHARE_MEMORY_END; 
  } 
 
  char p = 0; 
  char* q = (char*)lpShareMemory; 
  do  
  { 
    p = getchar(); 
    if (WaitForSingleObject(hClientReadOver, 5*1000) != WAIT_OBJECT_0)  
      goto SERVER_SHARE_MEMORY_END; 
    q[0] = p; 
    if (!ResetEvent(hClientReadOver)) goto SERVER_SHARE_MEMORY_END;//把指定的事件對象設置為無信號狀態(tài) 
    if (!SetEvent(hServerWriteOver)) goto SERVER_SHARE_MEMORY_END;//把指定的事件對象設置為有信號狀態(tài) 
  } while (p != '\n'); 
 
SERVER_SHARE_MEMORY_END: 
  //release share memory 
  if (NULL != hServerWriteOver)  CloseHandle(hServerWriteOver); 
  if (NULL != hClientReadOver)  CloseHandle(hClientReadOver); 
  if (NULL != lpShareMemory)   UnmapViewOfFile(lpShareMemory); 
  if (NULL != hFileMapping)    CloseHandle(hFileMapping); 
  if (NULL != hMutex)       ReleaseMutex(hMutex); 
  return 0; 
} 

客戶端:

#include "stdafx.h" 
#include <Windows.h> 
#include <iostream> 
using namespace std; 
int main() 
{ 
  HANDLE hMutex      = NULL; 
  HANDLE hFileMapping   = NULL; 
  LPVOID lpShareMemory  = NULL; 
  HANDLE hServerWriteOver = NULL; 
  HANDLE hClientReadOver = NULL; 
 
  hMutex = OpenMutex(MUTEX_ALL_ACCESS, 
    FALSE, 
    L"SM_Mutex"); 
  if (NULL == hMutex) 
  { 
    if (ERROR_FILE_NOT_FOUND == GetLastError()) 
    { 
      cout << "OpenMutex fail: file not found!" << endl; 
      goto CLIENT_SHARE_MEMORY_END; 
    } 
    else 
    { 
      cout << "OpenMutex fail:" << GetLastError() << endl; 
      goto CLIENT_SHARE_MEMORY_END; 
    } 
  } 
 
  if (WaitForSingleObject(hMutex, 5000) != WAIT_OBJECT_0)//hMutex 一旦互斥對象處于有信號狀態(tài),則該函數(shù)返回 
  { 
    DWORD dwErr = GetLastError(); 
    goto CLIENT_SHARE_MEMORY_END; 
  } 
 
  //open share memory 
  hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, 
    FALSE, 
    L"ShareMemoryTest"); 
  if (NULL == hFileMapping) 
  { 
    cout << "OpenFileMapping" << GetLastError() << endl; 
    goto CLIENT_SHARE_MEMORY_END; 
  } 
 
  lpShareMemory = MapViewOfFile(hFileMapping, 
    FILE_MAP_ALL_ACCESS, 
    0, 
    0, 
    0); 
  if (NULL == lpShareMemory) 
  { 
    cout << "MapViewOfFile" << GetLastError() << endl; 
    goto CLIENT_SHARE_MEMORY_END; 
  } 
 
  //read and write data 
  hServerWriteOver = CreateEvent(NULL, 
    TRUE, 
    FALSE, 
    L"ServerWriteOver"); 
  hClientReadOver = CreateEvent(NULL, 
    TRUE, 
    FALSE, 
    L"ClientReadOver"); 
  if (NULL == hServerWriteOver || 
    NULL == hClientReadOver) 
  { 
    cout << "CreateEvent" << GetLastError() << endl; 
    goto CLIENT_SHARE_MEMORY_END; 
  } 
 
  char p = 0; 
  char* q = (char*)lpShareMemory; 
  do  
  { 
    if (!SetEvent(hClientReadOver))  
      goto CLIENT_SHARE_MEMORY_END; 
 
    if (WaitForSingleObject(hServerWriteOver, INFINITE) != WAIT_OBJECT_0)  
      goto CLIENT_SHARE_MEMORY_END;  
 
    p = q[0]; 
    putchar(p); 
    if (!ResetEvent(hServerWriteOver))  
      goto CLIENT_SHARE_MEMORY_END; 
  } while (p != '\n'); 
 
CLIENT_SHARE_MEMORY_END: 
  //release share memory 
  if (NULL != hServerWriteOver)  CloseHandle(hServerWriteOver); 
  if (NULL != hClientReadOver)  CloseHandle(hClientReadOver); 
  if (NULL != lpShareMemory)   UnmapViewOfFile(lpShareMemory); 
  if (NULL != hFileMapping)    CloseHandle(hFileMapping); 
  if (NULL != hMutex)       ReleaseMutex(hMutex); 
  return 0; 
}

相關文章

  • C++實現(xiàn)俄羅斯方塊小游戲

    C++實現(xiàn)俄羅斯方塊小游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)俄羅斯方塊小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • QT出現(xiàn)沒有MySQL驅動手動編譯詳細步驟

    QT出現(xiàn)沒有MySQL驅動手動編譯詳細步驟

    這篇文章主要給大家介紹了關于QT出現(xiàn)沒有MySQL驅動手動編譯詳細步驟的相關資料,文中通過圖文介紹的非常詳細,對大家學習或者使用QT具有一定的參考學習價值,需要的朋友可以參考下
    2023-04-04
  • VC獲取當前路徑及程序名的實現(xiàn)代碼

    VC獲取當前路徑及程序名的實現(xiàn)代碼

    VC上或取當前路徑有多種方法,最常用的是使用 GetCurrentDirectory和GetModuleFileName函數(shù),個中都有諸多注意事項,特別總結一下
    2016-11-11
  • C++?正則表達式的應用詳解

    C++?正則表達式的應用詳解

    正則表達式(regular?expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等
    2021-11-11
  • TensorFlow源代碼構建流程記錄解析

    TensorFlow源代碼構建流程記錄解析

    這篇文章主要為大家介紹了TensorFlow源代碼構建流程記錄解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • C語言實現(xiàn)輸出各種三角形

    C語言實現(xiàn)輸出各種三角形

    這篇文章主要介紹了C語言實現(xiàn)輸出各種三角形方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • C++ 動態(tài)內存分配詳解(new/new[]和delete/delete[])

    C++ 動態(tài)內存分配詳解(new/new[]和delete/delete[])

    這篇文章主要介紹了C++ 動態(tài)內存分配詳解(new/new[]和delete/delete[]),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • CMake語法及CMakeList.txt簡單使用小結

    CMake語法及CMakeList.txt簡單使用小結

    Cmake主要用于開發(fā)跨平臺的C++項目,本文主要介紹了CMake語法及CMakeList.txt簡單使用小結,具有一定的參考價值,感興趣的可以了解一下
    2022-05-05
  • C語言實現(xiàn)哈希搜索算法及原理詳解

    C語言實現(xiàn)哈希搜索算法及原理詳解

    本文主要介紹了C語言實現(xiàn)哈希搜索算法及原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • C++ opencv霍夫圓檢測使用案例詳解

    C++ opencv霍夫圓檢測使用案例詳解

    這篇文章主要介紹了C++ opencv霍夫圓檢測使用案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09

最新評論

来凤县| 青铜峡市| 桓台县| 于都县| 五原县| 晋江市| 公主岭市| 淮北市| 岳西县| 邵阳县| 鄂尔多斯市| 顺平县| 江西省| 开江县| 原平市| 北海市| 容城县| 北安市| 德清县| 盐津县| 浑源县| 宁波市| 灵璧县| 昂仁县| 淮阳县| 五华县| 雷州市| 泸溪县| 龙山县| 奇台县| 玉林市| 侯马市| 隆安县| 新田县| 鹤岗市| 连云港市| 炎陵县| 高邮市| 福海县| 北安市| 宁波市|