Windows下基于共享内存实现进程间通信

Windows下基于共享内存实现进程间通信

案例场景描述:

  • 进程A申请共享内存,同时创建互斥量,取得互斥量的所有权后,向共享内存中写入数据,之后释放互斥量
  • 进程B打开共享内存,请求互斥量的所有权,读取共享内存数据,之后释放互斥量

进程A代码

  基于共享内存的方式实现进程间通信在效率上具有明显的优势,代码也非常简洁。
  对于需要传递大量数据的场景来说,可以将共享内存的地址空间进行强制类型转换,结构体是一种非常好的选择。
  但需要注意的是,这种方式只可以是C风格的类型,因为强制类型转换不会调用构造函数。
  如果在SharedMemoryContents这个结构体中加入std::list成员,可能会引起崩溃,因为它无法被正确初始化。

//------------------------进程A初始化------------------------------
const unsigned long BUF_SIZE = sizeof(SharedMemContents);
bool valid = true;	//校验进程A的初始化是否正确执行

//创建共享文件句柄,具有读写权限
HANDLE sharedMemHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 
	0, BUF_SIZE, L"SharedMemory");
if (sharedMemHandle == nullptr)
{
	valid = false;
	return;
}
//将共享内存的全部空间映射为自定义的结构体类型
SharedMemContents *pcontents = (SharedMemContents*)MapViewOfFile(sharedMemHandle, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if (pcontents == nullptr)
{
	valid = false;
	return;
}

//清理pcontents的内容
pcontents->tableRows = 0;
memset(pcontents->otherTitle, 0, 1024 * 5);
memset(pcontents->tableTitles, 0, 1024 * 5);

//创建互斥量,如果bInitialOwner设为true,会导致后面即使ReleaseMutex后,进程B也无法获得所有权,未明原因?
HANDLE mutexHandle = CreateMutex(nullptr, false, L"SharedMemory_mutex");
if (mutexHandle == nullptr)
{
	valid = false;
	return;
}
//------------------------进程A将数据写入共享内存------------------------------
//获取互斥量的所有权
DWORD wait_res = WaitForSingleObject(mutexHandle, INFINITE);
switch (wait_res)
{
case WAIT_ABANDONED:
	valid = false;
	return;
case WAIT_OBJECT_0:
	memcpy(pcontents->otherTitle, other_title.c_str(), other_title.size());
	memcpy(pcontents->tableTitles, table_title.c_str(), table_title.size());
	ReleaseMutex(mutexHandle);
}
//------------------------进程A结束前的清理工作------------------------------
ReleaseMutex(mutexHandle);
CloseHandle(mutexHandle);
UnmapViewOfFile(pcontents);
CloseHandle(sharedMemHandle);
pcontents = nullptr;

进程B代码

//------------------------进程B初始化-------------------------
//打开共享内存,只有读权限
HANDLE shm_handle = OpenFileMapping(FILE_MAP_READ, false, L"SharedMemory");
if (!shm_handle)
{
	return -1;
}
//获取共享内存的地址,并将其全部空间映射为结构体类型
SharedMemContents *pcontents = (SharedMemContents*)MapViewOfFile(
	shm_handle, FILE_MAP_READ, 0, 0, sizeof(SharedMemContents));
if (!pcontents)
{
	CloseHandle(shm_handle);
	return -1;
}
//打开互斥量,这里其实使用CreateMutex也是一样的,只要同名,仍然可以获得同一个互斥量的句柄
HANDLE mutex_handle = OpenMutex(MUTEX_ALL_ACCESS, false, L"SharedMemory_mutex");
if (!mutex_handle)
{
	UnmapViewOfFile(pcontents);
	CloseHandle(shm_handle);
	return -1;
}
//------------------------进程B读取共享内存数据-------------------------
while (true)
{
	//请求互斥量的所有权,保持等待
	DWORD wait_res = WaitForSingleObject(mutex_handle, INFINITE);
	switch (wait_res)
	{
	case WAIT_OBJECT_0:
	{
		//获取互斥量的所有权
		std::cout << pcontents->otherTitle << "\n"
			<< pcontents->tableTitles << "\n";

		for (int i = 0; i < pcontents->tableRows; ++i)
		{
			for (int j = 0; j < 21; ++j)
			{
				std::cout << pcontents->tableValues[i * 21 + j] << ",";
			}
			std::cout << "\n";
		}
		ReleaseMutex(mutex_handle);
		break;
	}
	case WAIT_ABANDONED:
		//TODO 这里的设计有缺陷,
		//在进程退出时,如果没有ReleaseMutex,等待的结果才会是WAIT_ABANDONED
		//而进程A退出时,主动释放了互斥量,把return放在这里,可能会陷入死循环
		ReleaseMutex(mutex_handle);
		CloseHandle(mutex_handle);
		UnmapViewOfFile(pcontents);
		CloseHandle(shm_handle);
		return true;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值