利用共享内存机制实现进程通信

这是我的第一篇CSDN文章,深知自己很菜,只为留下记录,方便日后查看!

进程间通信最简单的就是同一机器上两个进程之间的通信,进程1在共享内存中写入数据,进程2从共享内存中读出数据,或者两个进程均可对共享内存进行读写,我写的是最简单的情况:进程1写入数据,进程2读出数据。
首先,进程1需要调用内存映射API函数CreateFileMapping()创建一个有名字标识的共享内存

HANDLE handle1 = CreateFileMapping(
	INVALID_HANDLE_VALUE,				//映射文件的句柄,若设为0xFFFFFFFF则创建一个进程间共享的对象
	NULL,								//安全描述符
	PAGE_READWRITE,						//安全属性DWORD flProtect, 保护方式
	0,									//文件映射低32位最大长度
	1024,								//文件映射低32位最大长度
	"FirstShareFile"					//文件映射对象名称
);

handle1是由用户自定义的名称
接着最好判断一下是否创建成功:

if (handle1 == NULL)
{
	std::cout << "share memory error" << std::endl;
}

接下来,在创建文件映射对象后,进程1调用MapViewOfFile()函数映射到本进程的地址空间内

PINT lpbuf = (PINT)MapViewOfFile(
	handle1,							//CreateFileMapping()返回的文件映像对象句柄
	FILE_MAP_ALL_ACCESS,				//访问权限
	0,									//文件映射起始偏移的高32位
	0,									//文件映射起始偏移的低32位
	1024								//文件中要映射的字节数,为0表示映射整个文件映射对象
);

注意:这里我用 PINT 定义了 lpbuf 是因为我后面要往共享内存里写入整数,如果要往共享内存里写入字符串可以用 LPVOID 定义 lpbuf
同样,最好再次判断一下是否映射成功,不成功则结束程序

if (lpbuf == NULL)
{
	std::cout << "lpbuf error" << std::endl;
	CloseHandle(handle1);
	return -0;
}

接下来创建互斥量

HANDLE myHMutex = CreateMutex(NULL, FALSE, "MYMUTEX");//创建一个有名或者无名互斥量对象
HANDLE myHEvent = CreateEvent(NULL, FALSE, FALSE, "MYEVENT");//创建事件对象(安全属性,复位方式,初始状态,对象名称)

完成了需要在共享内存中写入数据的准备工作(并非以上工作,而是你的程序主体要干什么)后,就可以往共享内存中写入数据了

WaitForSingleObject(myHMutex, INFINITE);	//等待取得互斥对象的拥有权,进而访问共享资源
*lpbuf = sharenumber;						//将sharenumber写入共享内存,sharenumber就是我的两个进程相互通信的data
ReleaseMutex(myHMutex);						//访问完共享资源后,当前进程线程释放Mutex对象的拥有权 
SetEvent(myHEvent);							//设置信号

接下来是进程2的工作,进程2 要从共享内存中读取进程1写入共享内存中的数据
首先,进程2需要通过内存对象名调用OpenFileMapping()函数,以获得共享内存对象的句柄,并判断操作是否成功

HANDLE handle2 = OpenFileMapping(
	FILE_MAP_READ,					//访问数据的权限
	FALSE,							//是否继承句柄
	"FirstShareFile"				//要打开的文件映射对象名称
);
if (handle2 == NULL)
{
	std::cout << "share mempry error" << std::endl;
}

如果进程2获得共享内存对象的句柄成功,则调用MapViewOfFile()函数来映射对象视图,并判断是否映射成功

PINT lpbuf = (PINT)MapViewOfFile(
	handle2,						//CreateFileMapping()返回的文件映像对象句柄
	FILE_MAP_READ,					//访问权限
	0,								//文件映射起始偏移的高32位
	0,								//文件映射起始偏移的低32位
	1024							//文件中要映射的字节数,为0表示映射整个文件映射对象
);
if (lpbuf == NULL)
{
	std::cout << "lpbuf error" << std::endl;
	CloseHandle(handle2);
	return -0;
}

创建互斥量

HANDLE myHMutex = CreateMutex(NULL, FALSE, "MYMUTEX");//创建一个有名或者无名互斥量对象
HANDLE myHEvent = CreateEvent(NULL, FALSE, FALSE, "MYEVENT");//创建事件对象(安全属性,复位方式,初始状态,对象名称)

映射成功后,就可以从共享内存中读取数据了

WaitForSingleObject(myHMutex, INFINITE);	//等待取得互斥对象的拥有权,进而访问共享资源
sharednumber = *lpbuf;						//从lpbuf中读取数据到sharednumber
ReleaseMutex(myHMutex);						//访问完共享资源后,当前进程线程释放Mutex对象的拥有权 
SetEvent(myHEvent);							//设置信号

当进程2结束使用共享内存后,调用UnmapViewOfFile()函数以取消其地址空间内的视图

if (lpbuf)
{
	UnmapViewOfFile(lpbuf);
	lpbuf = NULL;
}

下面是一些补充:
1.如果要往共享内存中读写字符串则可以这样做:
映射内存时用 LPVOID 定义而不用 PINT

LPVOID lpbuf = MapViewOfFile(
	handle2,						//CreateFileMapping()返回的文件映像对象句柄
	FILE_MAP_READ,					//访问权限
	0,								//文件映射起始偏移的高32位
	0,								//文件映射起始偏移的低32位
	1024							//文件中要映射的字节数,为0表示映射整个文件映射对象
);

读写数据时使用内存复试函数memcpy()
ReadBufWriteBuf是提前在进程2和进程1中定义好的用于读/写数据的char型数据

char ReadBuf[2] = "1";
char WriteBuf[2] = "1";

从共享内存中读取,使用(char *)lpbuf则读取到的是lpbuf中的数据,而非地址

memcpy(ReadBuf, (char *)lpbuf, 2);

写数据到共享内存

memcpy(lpbuf, WriteBuf, strlen(WriteBuf));

以下内容是我利用以上共享内存机制实现的两个进程之间的通信,功能是:进程1每200ms计数一次,每计数到60,则写入共享内存中的数值+1且进程1又从0开始计数,然后进程2读取进程1写入共享内存的数值并显示,有兴趣的话可以看看
以下是两个进程通信的视频展示,原项目文件可以在本文开头下载。

进程通信计数视频


如果我的文章有幸被您看到,希望您能不吝赐教,向您学习,感觉写的不错的话请点个赞哦。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没伞的行者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值