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

文章目录

  • 前言
  • 一、Windows 进程间共享内存通信
  • 二、 案例:
  • 总结


前言

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


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

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

1、进程间通信原理:

C++ 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;
Destination A pointer to the starting address of the copied block’s destination.
Source A pointer to the starting address of the block of memory to copy.
Length The 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;
Destination A pointer to the starting address of the move destination.
Source A pointer to the starting address of the block of memory to be moved.
Length The 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.

二、 案例:

C++ Windows进程间共享内存通信_第2张图片

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

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);
}

总结

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

你可能感兴趣的:(C++,Visual,windows,c++,microsoft)