C++ Windows进程间共享内存通信


前言

在项目工程中需要64位程序调用32位程序并加以通信。 实现了两个进程间的内存共享。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Windows 进程间共享内存通信

1、进程间通信原理:

在这里插入图片描述

主要实现:
• 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。
• 可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存。
• 可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。

2、使用到的API

typedef struct _SYSTEM_INFO {
  union {
    DWORD dwOemId; //为了兼容而保留的已过时成员。
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;
    } DUMMYSTRUCTNAME;
  } DUMMYUNIONNAME;
  DWORD     dwPageSize;  //页面大小和页面保护和承诺的粒度。这是VirtualAlloc函数使用的页面大小
  LPVOID    lpMinimumApplicationAddress;//指向应用程序和动态链接库可访问的·最低·内存地址的指针,(DLL)
  LPVOID    lpMaximumApplicationAddress; //指向应用程序和DLL可访问的·最高·内存地址的指学针
  DWORD_PTR dwActiveProcessorMask; //一个掩码,表示配置未系统中的处理器集。位0时处理器0;位31时处理器31
  DWORD     dwNumberOfProcessors; //当前组中的逻辑处理器数。
  DWORD     dwProcessorType; //处理器类型
  DWORD     dwAllocationGranularity;  //可在其中分配虚拟内存的起始地址的粒度。
  WORD      wProcessorLevel; //依赖于体系结构的处理器级别。它应仅用于显示目的。
  WORD      wProcessorRevision;//依赖于体系结构的处理器修订版本。
} SYSTEM_INFO, *LPSYSTEM_INFO; //系统用信息

SYSTEM_INFO结构 ——sysinfoapi.h

1、GetSystemInfo

参数功能
[out] LPSYSTEM_INFO lpSystemInfo指向接受信息的SYSTEM_INFOj结构的指针

2、HANDLE CreateFileMapping( HANDLE hFile,LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName ); —创建共享内存

参数功能
HANDLE物理文件句柄,返回值
HANDLE hFile物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes安全设置(一般位NULL)
DWORD dwMaximumSizeHigh高位文件大小
DWORD dwMaximumSizeLow低位文件大小
LPCTSTR lpName共享内存名称

3、HANDLE OpenFileMapping(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName ); --打开一个又名的共享内存

参数功能
HANDLE[返回值]成功打开lpName名字的共享内存地址;失败,返回NULL
DWORD dwDesiredAccess通道模式
BOOL bInheritHandle继承标志位
LPCTSTR lpName文件映射目标的名称指针

4、LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap); --映射共享内存地址空间

参数介绍
LPVOID[返回]成功:映射的地址;失败:NULL
HANDLE hFileMappingObject文件映射目标到映射到地址空间
DWORD dwDesiredAccess存取模式
DWORD dwFileOffsetHigh高阶 32 位文件偏移量
DWORD dwFileOffsetLow低阶32位文件偏移量
DWORD dwNumberOfBytesToMap映射字节位数

5、BOOL UnmapViewOfFile( LPCVOID lpBaseAddress ); --解除映射

参数介绍
BOOL[返回] 成功:非0; 失败:0;
LPCVOID lpBaseAddress映射地址起始位置, MapViewOfFile 的句柄

6、BOOL CloseHandle(HANDLE hObject) --关闭打开的句柄

参数介绍
BOOL[返回]成功:true;失败:false;
HANDLE hObject要关闭的目标句柄

二、信号量:
在另个进程访问共享内存时,会造成数据访问冲突。需要使用信号量来限制该访问顺序。

1、CreateSemaphore 创建信号量对象

HANDLE WINAPI CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,
LONG lMaximumCount,LPCTSTR lpName);

参数介绍
HANDLE[返回]成功:返回信号量句柄;失败:NULL;
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,设置安全属性
LONG lInitialCount初始的计数值
LONG lMaximumCount最大的计数值
LPCTSTR lpName对信号量对象命名

2、OpenSemaphore 通过信号量名,获得信号量对象句柄

HANDLE WINAPI OpenSemaphore(DWORD dwDesireAccess,BOOL bInheritHandle,LPCTSTR lpName);

参数介绍
HANDLE[返回]成功:返回信号量句柄;失败:NULL;
DWORD dwDesireAccess-SEMAPHORE_ALL_ACCESS-
BOOL bInheritHandle是否继承
LPCTSTR lpName信号量名称

3、ReleaseSemaphore释放信号量

BOOL WINAPI ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount,LPLONG lpPreviousCount);

参数介绍
BOOL[返回]成功:true;失败:false;
HANDLE hSemaphore信号量句柄
LONG lReleaseCount可以释放多个计数
LPLONG lpPreviousCount上一个计数

4、WaitForSingleObject 等待指定对象处于信号状态或超时间隔已过

DWORD WaitForSingleObject( [in] HANDLE hHandle, [in] DWORD dwMilliseconds)

参数介绍
DWORD[返回]成功,则返回值指示导致函数返回的事件。失败:返回错误代码
[in] HANDLE hHandle对象的句柄
[in] DWORD dwMilliseconds超时间隔(以毫秒为单位)

函数检查指定对象的当前状态。 如果对象的状态未对齐,则调用线程将进入等待状态,直到发出该对象信号或超时间隔。
该函数修改某些类型的同步对象的状态。 修改仅适用于指示状态导致函数返回的对象。 例如,信号灯对象的计数减少一个。


三、从内存中取值

1、CopyMemory 拷贝内存数据

void CopyMemory( In PVOID Destination, In const VOID *Source, In SIZE_T Length);

参数介绍
void[返回]成功:true;失败:false;
DestinationA pointer to the starting address of the copied block’s destination.
SourceA pointer to the starting address of the block of memory to copy.
LengthThe size of the block of memory to copy, in bytes.

如果源块和目标块重叠,则结果未定义。对于重叠块,请使用MoveMemory函数。

2、MoveMemory 拷贝内存数据

void MoveMemory( In PVOID Destination, In const VOID *Source, In SIZE_T Length);

参数介绍
void[返回]成功:true;失败:false;
DestinationA pointer to the starting address of the move destination.
SourceA pointer to the starting address of the block of memory to be moved.
LengthThe size of the block of memory to move, in bytes.

This function is defined as the RtlMoveMemory function. Its implementation is provided inline. The source and destination blocks may overlap.

二、 案例:

流程图

结论:操纵同一块内存地址。

Server服务器:

void SharedMemory()
{
	HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
		NULL,
		PAGE_READWRITE,
		0,
		256,
		TEXT("MySharedMemory")
		);
	LPBYTE pcMap = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 
									0, 0, 0);
 
	char *pSharedStr = "0this is my shared memory";
	memcpy(pcMap, pSharedStr, strlen(pSharedStr));
 
	while (pcMap[0] == '0')	
	{
		Sleep(100);
	}
 
	// 释放内存
	UnmapViewOfFile(pcMap);
	CloseHandle(hFileMapping);
}

Client 客户端

void TestSharedMemory()
{
	HANDLE hFileMapping;
	LPBYTE pcMap;
 
	hFileMapping = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, TEXT("MySharedMemory"));  
	if(hFileMapping == NULL)
	{
		return;
	}
 
	pcMap = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS,
		0, 0, 0);
 
 
	cout << pcMap << endl;
 
	// 通知主程序释放
	pcMap[0] = '1';
 
 
	// 释放内存
	UnmapViewOfFile(pcMap);
	CloseHandle(hFileMapping);
}

总结

这次先写到这里,例子下次再写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值