c++中共享内存原理及实现——三步走

一、什么是共享内存

文件映射是一种实现进程间单向或双向通信的机制。它允许两个或多个本地进程间相互通信。为了共享文件或内存,所有的进程必须使用相同的文件映射的名字或是句柄。

 

二、实现步骤

为了实现共享文件,第一个进程先调用CreateFile方法。接下来调用CreateFileMapping方法来创建一个文件映射对象。并为文件映射指明一个句柄和名称。由于事件,信号,互斥对象和文件映射等这些内核对象都共享同一个名字空间,所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。

为了实现共享内存,进程应首先调用 CreateFileMapping 函数然后在 hFile 参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE,那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。使用共享内存或文件的进程必须使用MapViewOfFile函数或MapViewOfFileEx函数来创建一个文件视图。

 

三、代码实现

#include
#include
#include 
#include 

using namespace std;


#pragma warning(disable:4996)
int main()
{
	string strMapName("ShareMemory");                // 内存映射对象名称
	string strComData("This is common data!");        // 共享内存中的数据
	  LPVOID pBuffer;                                    // 共享内存指针
	
	   // 首先试图打开一个命名的内存映射文件对象  
	    HANDLE hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, (LPCWSTR)strMapName.c_str());
	     if (NULL == hMap)
	    {    // 打开失败,创建之
	        hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,
		                                    NULL,
		                                  PAGE_READWRITE,
		                                    0,
	                                   strComData.length() + 1,
				(LPCWSTR)strMapName.c_str());
            //如果有问题用L"name"形式
	         // 映射对象的一个视图,得到指向共享内存的指针,设置里面的数据
			         pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
	         strcpy((char*)pBuffer, strComData.c_str());
	         cout << "写入共享内存数据:" << (char *)pBuffer << endl;
	     }
	     else
		     {    // 打开成功,映射对象的一个视图,得到指向共享内存的指针,显示出里面的数据
		        pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
		         cout << "读取共享内存数据:" << (char *)pBuffer << endl;
		     }
	
		     getchar();            // 注意,进程关闭后,所有句柄自动关闭,所以要在这里暂停
	
		    // 解除文件映射,关闭内存映射文件对象句柄
		     ::UnmapViewOfFile(pBuffer);
	    ::CloseHandle(hMap);
	     system("pause");
	     return 0;

    return 0;
}

使用时,连续打开两次Test.exe即可。

 

其中几个比较重要的函数讲解如下:

HANDLE CreateFileMapping(
  HANDLE hFile,                       //物理文件句柄
  LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
  DWORD flProtect,                    //保护设置
  DWORD dwMaximumSizeHigh,            //高位文件大小
  DWORD dwMaximumSizeLow,             //低位文件大小
  LPCTSTR lpName                      //共享内存名称
);
 

 hFile             指定欲在其中创建映射的一个文件句柄。INVALID_HANDLE_VALUE,即0xFFFFFFFF表示在页面文件中创建一个

                         可共享映射文件。

lpAttributes    它指明返回的句柄是否可以被子进程所继承,指定一个安全对象,在创建文件映射时使用。

                       如果为NULL(用ByVal As Long传递零),表示使用默认安全对象

 flProtect         有以下几种方式:

 

                            PAGE_READONLY 以只读方式打开映射

                            PAGE_READWRITE 以可读、可写方式打开映射

                           PAGE_WRITECOPY 为写操作留下备份

                 也可组合使用下述一个或多个常数:    

                           SEC_COMMIT    为文件映射一个小节中的所有页分配内存

                            SEC_IMAGE      文件是个可执行文件

                            SEC_RESERVE  为没有分配实际内存的一个小节保留虚拟内存空间

 

dwMaximumSizeHigh              文件映射的最大长度的高32位

dwMaximumSizeLow              文件映射的最大长度的低32位。如这个参数和dwMaximumSizeHigh都是零,就用磁盘文件的实际长度。

lpName                     指定文件映射对象的名字。如存在这个名字的一个映射,函数就会打开它。

                                 用vbNullString可以创建一个无名的文件映射。

LPVOID WINAPI MapViewOfFile(
  __in HANDLE hFileMappingObject,
  __in DWORD dwDesiredAccess, 
  __in DWORD dwFileOffsetHigh,
  __in DWORD dwFileOffsetLow,
  __in SIZE_T dwNumberOfBytesToMap
  );                             //将一个文件映射对象映射到当前应用程序的地址空间。

hFileMappingObject      为CreateFileMapping返回的文件映像对象句柄。

dwDesiredAccess          映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。

                                      可取以下值:

         

                                    FILE_MAP_ALL_ACCESS 等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ. 文件映射对

                                                                             象被创建时必须指定PAGE_READWRITE 选项.

                                    FILE_MAP_COPY           可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用

                                                                          CreateFileMapping时 必须 传入PAGE_WRITECOPY保护属性.

                                    FILE_MAP_EXECUTE  可以将文件中的数据在调用CreateFileMapping时可以传入

                                                                         PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ保护属性.

                                    FILE_MAP_READ        可以读取文件.在调用CreateFileMapping时可以传入PAGE_READONLY或

                                                                        PAGE_READWRITE保护属性.

                                   FILE_MAP_WRITE        可以读取和写入文件.在调用CreateFileMapping时必须传入

                                                                        PAGE_READWRITE保护属性.

 

dwFileOffsetHigh          表示文件映射起始偏移的高32位.

dwFileOffsetLow           表示文件映射起始偏移的低32位.(64KB对齐不是必须的)

dwNumberOfBytes             指定映射文件的字节数.
 

你可能感兴趣的:(c++基础的深入浅出)