织梦CMS - 轻松建站从此开始!

罗索

用文件映射(File Mapping)实现进程间内存共享

jackyhwei 发布于 2011-12-15 11:29 点击:次 
下面就用文件映射(File Mapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(File Mapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。
TAG:

我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
下面就用文件映射(File Mapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(File Mapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。
在该例子里,实现了下面5个函数用来进行进程间的内存共享。可以把这5个函数放到一个DLL里面当成输出函数来用。在进程里加载该DLL并调用相应的函数就可实现进程间内存共享。
首先,定义返回值代码:

  1. typedef enum 
  2.     LX_OK                                = 0, // 正常返回 
  3.     LX_SHAREDMEMORY_EXISTS  = 1, // 共享内存已经存在 
  4.     LX_INVALID_SHAREDMEMORY = 2, // 共享内存错误返回 
  5.     LX_INVALID_SIZE                 = 3  // 共享内存大小错误 
  6. }LX_RETURN_VALUE; 

然后,是函数声明:

  1. // 创建共享内存 
  2. LX_RETURN_VALUE CreateSharedMemory(UINT nSize); 
  3. // 释放共享内存 
  4. LX_RETURN_VALUE ReleaseSharedMemory(); 
  5. // 得到共享内存大小 
  6. LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize); 
  7. // 向共享内存写入数据 
  8. LX_RETURN_VALUE WriteToSharedMemory(void *pData, UINT nSize); 
  9. // 从共享内存读取数据 
  10. LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize); 

下面是函数的实现:

  1. // 自动Lock和Unlock互斥量 
  2. struct CAutoMutex 
  3.     CAutoMutex(); 
  4.     ~CAutoMutex(); 
  5.  
  6.     // 互斥量 
  7.     static CMutex m_mutex; 
  8. }; 
  9.  
  10. CMutex CAutoMutex::m_mutex(FALSE, "StarLeeMutex"); 
  11.  
  12. CAutoMutex::CAutoMutex() 
  13.     m_mutex.Lock(); 
  14.  
  15. CAutoMutex::~CAutoMutex() 
  16.     m_mutex.Unlock(); 
  17.  
  18. LX_RETURN_VALUE CreateSharedMemory(UINT nSize) 
  19.     // 创建共享内存块 
  20.     HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE
  21. , NULL, PAGE_READWRITE, 0, nSize, "StarLeeSharedMemory"); 
  22.  
  23.     // 创建错误 
  24.     if ((hFileMapping == NULL) || (hFileMapping == INVALID_HANDLE_VALUE)) 
  25.         return LX_INVALID_SHAREDMEMORY; 
  26.  
  27.     // 共享内存已经存在 
  28.     if (GetLastError() == ERROR_ALREADY_EXISTS) 
  29.         return LX_SHAREDMEMORY_EXISTS; 
  30.  
  31.     // 创建另外一块内存存放共享内存的大小 
  32.     HANDLE hSize = CreateFileMapping(NULL, NULL, PAGE_READWRITE
  33. , 0, sizeof(UINT), "StarLeeSharedMemorySize"); 
  34.  
  35.     if ((hSize == NULL) || (hSize == INVALID_HANDLE_VALUE)
  36.  || (GetLastError() == ERROR_ALREADY_EXISTS)) 
  37.         return LX_INVALID_SHAREDMEMORY; 
  38.  
  39.     // 得到存放共享内存大小的指针 
  40.     UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_WRITE, 0, 0, sizeof(UINT)); 
  41.  
  42.     if (pSize == NULL) 
  43.         return LX_INVALID_SHAREDMEMORY; 
  44.  
  45.     // 写入共享内存的大小 
  46.     memcpy(pSize, &nSize, sizeof(UINT)); 
  47.  
  48.     UnmapViewOfFile(pSize); 
  49.  
  50.     return LX_OK; 
  51.  
  52. LX_RETURN_VALUE ReleaseSharedMemory() 
  53.     CAutoMutex MutexLock; 
  54.  
  55.     // 打开共享内存 
  56.     HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS
  57. , FALSE, "StarLeeSharedMemory"); 
  58.  
  59.     // 关闭共享内存 
  60.     if (hFileMapping != NULL) 
  61.         CloseHandle(hFileMapping); 
  62.  
  63.     // 打开存放共享内存大小的文件映射 
  64.     HANDLE hSize = OpenFileMapping(FILE_MAP_ALL_ACCESS
  65. , FALSE, "StarLeeSharedMemorySize"); 
  66.  
  67.     // 关闭存放共享内存大小的文件映射 
  68.     if (hSize != NULL) 
  69.         CloseHandle(hSize); 
  70.  
  71.     return LX_OK; 
  72.  
  73. LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize) 
  74.     CAutoMutex MutexLock; 
  75.  
  76.     HANDLE hSize = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemorySize"); 
  77.  
  78.     if (hSize == NULL) 
  79.         return LX_INVALID_SHAREDMEMORY; 
  80.  
  81.     UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_READ, 0, 0, sizeof(UINT)); 
  82.  
  83.     if (pSize == NULL) 
  84.         return LX_INVALID_SHAREDMEMORY; 
  85.  
  86.     // 得到共享内存的大小 
  87.     memcpy(&nSize, pSize, sizeof(UINT)); 
  88.  
  89.     return LX_OK; 
  90.  
  91. LX_RETURN_VALUE WriteToSharedMemory(void *pDate, UINT nSize) 
  92.     UINT nSharedMemorySize = 0; 
  93.  
  94.     // 得到共享内存的大小 
  95.     if (GetSharedMemorySize(nSharedMemorySize) != LX_OK) 
  96.         return LX_INVALID_SHAREDMEMORY; 
  97.  
  98.     // 检查共享内存的大小 
  99.     if (nSize > nSharedMemorySize) 
  100.         return LX_INVALID_SIZE; 
  101.  
  102.     CAutoMutex MutexLock; 
  103.  
  104.     HANDLE hFileMapping = OpenFileMapping(FILE_MAP_WRITE, FALSE, "StarLeeSharedMemory"); 
  105.  
  106.     if (hFileMapping == NULL) 
  107.         return LX_INVALID_SHAREDMEMORY; 
  108.  
  109.     void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, nSize); 
  110.  
  111.     if (pMapView == NULL) 
  112.         return LX_INVALID_SHAREDMEMORY; 
  113.  
  114.     // 清空共享内存 
  115.     memset(pMapView, 0, nSharedMemorySize); 
  116.  
  117.     // 将数据写入共享内存 
  118.     memcpy(pMapView, pDate, nSize); 
  119.  
  120.     UnmapViewOfFile(pMapView); 
  121.  
  122.     return LX_OK; 
  123.  
  124. LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize) 
  125.     UINT nSharedMemorySize = 0; 
  126.  
  127.     if (GetSharedMemorySize(nSharedMemorySize) != LX_OK) 
  128.         return LX_INVALID_SHAREDMEMORY; 
  129.  
  130.     if (nSize > nSharedMemorySize) 
  131.         return LX_INVALID_SIZE; 
  132.  
  133.     CAutoMutex MutexLock; 
  134.  
  135.     HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemory"); 
  136.  
  137.     if (hFileMapping == NULL) 
  138.         return LX_INVALID_SHAREDMEMORY; 
  139.  
  140.     void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, nSize); 
  141.  
  142.     if (pMapView == NULL) 
  143.         return LX_INVALID_SHAREDMEMORY; 
  144.  
  145.     // 从共享内存读取数据 
  146.     memcpy(pData, pMapView, nSize); 
  147.  
  148.     UnmapViewOfFile(pMapView); 
  149.  
  150.     return LX_OK; 

对于代码中能自动锁定和结锁互斥量的结构AutoMutex,可以参考我的《巧用构造函数与析构函数对数据进行设置和恢复》。

(starlee)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201112/15482.html]
本文出处:CSDN博客 作者:starlee 原文
顶一下
(3)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容