在Windows系列操作系统下,任何一个进程不允许读取、写入或是修改另一个进程的数据(包括变量、对象和内存分配等),但是在某个进程内创建的文件映射对象的视图却能够为多个其他进程所映射,这些进程共享的是物理存储器的同一个页面。因此,当一个进程将数据写入此共享文件映射对象的视图时,其他进程可以立即获取数据变更情况。为了进一步提高数据交换的速度,还可以采用由系统页文件支持的内存映射文件而直接在内存区域使用,显然这种共享内存的方式是完全可以满足在进程间进行大数据量数据快速传输任务要求的。下面给出在两个相互独立的进程间通过文件映射对象来分配和访问同一个共享内存块的应用实例。在本例中,由发送方程序负责向接收方程序发送数据,文件映射对象由发送方创建和关闭,并且指定一个唯一的名字供接收程序使用。接收方程序直接通过这个唯一指定的名字打开此文件映射对象,并完成对数据的接收。
在发送方程序中,首先通过CreateFileMapping()函数创建一个内存映射文件对象,如果创建成功则通过MapViewOfFile()函数将此文件映射对象的视图映射进地址空间,同时得到此映射视图的首址。
例如:
void* SetShareMemory(void** pShare,int Maxlen,char* name)
{
HANDLE hShare = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,
PAGE_READWRITE,0,Maxlen,name);
if (hShare != NULL)
{
*pShare = (char*)MapViewOfFile(hShare,FILE_MAP_WRITE,0,0,0);
}
if (*pShare == NULL)
{
CloseHandle(hShare);
hShare = NULL;
}
return hShare;
}
CreateFileMapping(HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName)
函数参数hFile指定了待映射到进程地址空间的文件句柄,如果为无效句柄则系统会创建一个使用来自页文件而非指定磁盘文件存储器的文件映射对象。很显然,在本例中为了数据能快速交换,需要人为将此参数设定为INVALID_HANDLE_VALUE;参数flProtect设定了系统对页面采取的保护属性,由于需要进行读写操作,因此可以设置保护属性PAGE_READWRITE;双字型参数dwMaximumSizeHigh和dwMaximumSizeLow指定了所开辟共享内存区的最大字节数;最后的参数lpName用来给此共享内存设定一个名字,接收程序可以通过这个名字将其打开。MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap)
函数的参数hFileMappingObject为CreateFileMapping()返回的内存文件映像对象句柄;参数dwDesiredAccess再次指定对其数据的访问方式,而且需要同CreateFileMapping()函数所设置的保护属性相匹配。这里对保护属性的重复设置可以确保应用程序能更多的对数据的保护属性进行有效控制。
数据的传送实际是将数据从发送方写到共享内存中,然后由接收程序及时从中取走即可。数据从发送方程序写到共享内存比较简单,只需用memcpy()函数将数据拷贝过去。
例如:
void SetShareMemoryInfo(void* inInfo,char* inBuf,int len)
{
//填充数据
memcpy(inInfo, inBuf, len);
}
最后共享内存使用完,需要将映射进来的内存文件映射对象视图卸载和资源的释放等处理。这部分工作主要由UnmapViewOfFile()和CloseHandle()等函数完成。
例如:
void CloseShare(void* lpShare,void* lpRevShare)
{
if (lpRevSHare != NULL)
{
UnmapViewOfFile(lpRevShare);
lpRevShare = NULL;
}
if (lpShare != NULL)
{
CloseHandle(lpShare);
lpShare = NULL;
}
}
程序中调用方法:
char* ShareInfo = NULL;
HANDLE pShare = NULL;
char buf[1024] = 'a';
s_pShare = SetShare((void**)&ShareInfo,1024,L"ShareMemory");//初始化
SetShareInfo(ShareInfo,buf,1024);//设置数据内容
CloseShare((void*)pShare,ShareInfo);//关闭
接收方,在windows mobile上是不支持 OpenFileMapping函数的,所以还需要使用CreateFileMapping函数实现.
例如:
Void* GetShareMemory(void** lpRev,int Maxlen,char* ShareName)
{
HANDLE lpFileMap= CreateFileMapping(INVALID_HANDLE_VALUE,NULL,
PAGE_READWRITE,0, Maxlen, ShareName);
if (lpFileMap != NULL)
{
*lpRev= (char*)MapViewOfFile(lpFileMap,FILE_MAP_READ,0,0,0);}
if ((*lpRev) ==NULL)
{
CloseHandle(lpFileMap);
lpFileMap=NULL;
}
return lpFileMap;
}
接收方从共享内存中取数据方法与发送放一样,只要把内存中的数据拷贝出来就可以了.
Void GetShareInfo(void* lpRev,char* lpInfo)
{
memcpy(lpInfo,lpRev,拷贝的长度);
}
释放操作同上.
调用方法:
HANDLE lpShare = NULL;
char* lpShareInfo = NULL;
lpShare = GetShareMemory ((void**)& lpShareInfo,1024,L”ShareMemory”);//初始化
char ShareInfo[1024];
GetShareMemoryInfo(lpShareInfo, &ShareInfo);//获取数据
CloseShare((void*)pShare,ShareInfo);//释放
希望以上能对您有所帮助.