这是我的第一篇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()
ReadBuf
和WriteBuf
是提前在进程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写入共享内存的数值并显示,有兴趣的话可以看看
以下是两个进程通信的视频展示,原项目文件可以在本文开头下载。
进程通信计数视频
如果我的文章有幸被您看到,希望您能不吝赐教,向您学习,感觉写的不错的话请点个赞哦。