您的位置:首页 > 其它

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

2015-06-20 15:50 302 查看
进程间通信的方法很多,共享内存便是其中的一种,其原理就是把一块物理内存,映射到两个不同进程的虚拟地址空间,这样一个进程对此块内存的操作就能被另一个进程看到。

windows下,使用共享内存有以下几个函数:

CreateFileMapping:用于创建映射文件对象。

OpenFileMapping:打开已存在的文件映射对象。

MapViewOfFile:把文件映射对象转为可读写的void 指针。

对于共享内存的读写,要利用windows提供的内核对象来实现读写进程之间的同步,比如信号量,事件等。在我自己的项目中,由于需要传输大量的数据,希望能够加快数据传输的速度,刚开始我设计的是把共享内存开大一点,比如100个数据单元。然后写进程循环写,读进程只要不遇到当前正在写的单元,就直接读,否则等待。通过实践发现,这种方式不仅没有加快数据传输的速度,反而会出现传输速度时快时慢,随机丢失数据等问题。这是因为我对写进程没有做任何限制,一直循环写。这样做是出于这样的一个前提:假设在同一台机器上的两个进程的速度应该差不多。实际上不能对CPU的调度做任何假设。改为利用事件同步两个进程这种方式后,速度明显比原来快,不丢数据,而且共享内存只需开一个数据单元大小。综上,应该多实践,而不是做一些没有依据的假设。

以下是一些测试的源代码,部分代码来自博客:http://blog.csdn.net/sszgg2006/article/details/8573348

服务端写进程:

#include<iostream>
#include<windows.h>
#include<tchar.h>
using namespace std;

HANDLE hShipFileMapping=NULL;
LPVOID lpShipMem    = NULL;
HANDLE hServerWriteOver = NULL;
HANDLE hClientReadOver  = NULL;

int main(int argc, char const *argv[])
{
while (!hShipFileMapping)
{
hShipFileMapping=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,
sizeof(int),_T("ShipMem"));
}

lpShipMem=MapViewOfFile(hShipFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);

if (!lpShipMem)
{
cout<<"MapView Of File failed : "<<GetLastError()<<endl;

return -1;
}
hServerWriteOver=CreateEvent(NULL,TRUE,FALSE,_T("ServerWriteOver"));
hClientReadOver=CreateEvent(NULL,TRUE,FALSE,_T("ClientReadOver"));
if(hServerWriteOver==NULL||hClientReadOver==NULL)
{
cout<<"CreateEvent : "<<GetLastError()<<endl;
}
int* lp=(int*)lpShipMem;
int i;
do
{
cin>>i;
WaitForSingleObject(hClientReadOver,INFINITE);
*lp=i;
ResetEvent(hClientReadOver);
SetEvent(hServerWriteOver);
}while(i!=0);

if(hShipFileMapping!=NULL)
CloseHandle(hShipFileMapping);
if(hServerWriteOver!=NULL)
CloseHandle(hServerWriteOver);
if(hClientReadOver!=NULL)
CloseHandle(hClientReadOver);

return 0;

}
客户端读进程:

#include<iostream>
#include<windows.h>
#include<tchar.h>
using namespace std;

HANDLE hShipFileMapping=NULL;
LPVOID lpShipMem    = NULL;
HANDLE hServerWriteOver = NULL;
HANDLE hClientReadOver  = NULL;

int main(int argc, char const *argv[])
{
while(!hShipFileMapping)
{
hShipFileMapping=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("ShipMem"));
}
if(!hShipFileMapping)

cout<<"open HLAObject FileMapping failed : "<<GetLastError()<<endl;

lpShipMem=MapViewOfFile(hShipFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);

if(!lpShipMem)

cout<<"MapViewOfFile failed :  "<<GetLastError()<<endl;
hServerWriteOver = CreateEvent(NULL,TRUE,FALSE,_T("ServerWriteOver"));
hClientReadOver = CreateEvent(NULL,TRUE,FALSE,_T("ClientReadOver"));
if (NULL == hServerWriteOver ||NULL == hClientReadOver)
{
cout << "CreateEvent" << GetLastError() << endl;
}

int i;
int* lp=(int*)lpShipMem;
do{
SetEvent(hClientReadOver);
WaitForSingleObject(hServerWriteOver,INFINITE);
i=*lp;
cout<<i<<endl;
ResetEvent(hServerWriteOver);
}while(1);

if(hShipFileMapping!=NULL)
CloseHandle(hShipFileMapping);
if(hServerWriteOver!=NULL)
CloseHandle(hServerWriteOver);
if(hClientReadOver!=NULL)
CloseHandle(hClientReadOver);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: