使用方式非常简单,需要的进程初始化类调用InitializeLock函数传入相同的字符串即可。可以多个进程使用PushString(),写入缓冲区,只允许一个进程进行调用PopString()读取,读取方面没有写保护锁,非线程安全。构造函数与析构函数看起来似乎不严谨,但不影响使用,有不对的地方望大牛提供指点。
测试代码用于获取通信所需的时间
#include "stdafx.h"
#include
#include
#include
#include
#include
#include "InterProcessCommunication.h"
inline long long str2longlong(std::string str)
{
long long result;
std::istringstream is(str);
is >> result;
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
Sleep(1000);
LARGE_INTEGER nEndTime;
LARGE_INTEGER nFreq;
QueryPerformanceFrequency(&nFreq);
InterProcessCommunication t_MultiProcessLock;
if(t_MultiProcessLock.InitializeLock("shared_memory"))
std::cout<<"初始化成功!";
std::string str;
while(true)
{
str=t_MultiProcessLock.PopString();
QueryPerformanceCounter(&nEndTime);
long long start=str2longlong(str);
double t=((double)(nEndTime.QuadPart-start))/nFreq.QuadPart*1000;
printf("%s--通信时间%.6fms\n",str.c_str(),t);
}
return 0;
}
#include "stdafx.h"
#include
#include
#include
using namespace std;
#include "InterProcessCommunication.h"
int _tmain(int argc, _TCHAR* argv[])
{
LARGE_INTEGER nFreq;
InterProcessCommunication t_MultiProcessLock;
if(t_MultiProcessLock.InitializeLock("shared_memory"))
std::cout<<"初始化成功!";
LARGE_INTEGER nBeginTime;
unsigned char str1[10];
QueryPerformanceFrequency(&nFreq);
while(1)
{
char a[10];
Sleep(100);
string ss;
ostringstream os;
QueryPerformanceCounter(&nBeginTime);
os<istringstream is(os.str());
is>>ss;
t_MultiProcessLock.PushString(ss.c_str());
std::cout<std::endl;
}
return 0;
}
#pragma once
#include
#include
#include
/**
*
* @Description windows共享内存多进程高效字符串数据传输,进程安全
* 允许多个进程同时写入缓冲区,只允许一个进程进行读取,读取方式为阻塞式
* @author kellygod
*
*/
#define BUFFER_MAX 4096
typedef struct _CircleBuffer{
unsigned int head_pos;
unsigned int tail_pos;
unsigned char circle_buffer[BUFFER_MAX];
}CircleBuffer;
typedef struct RWLock_s
{
long long count;
int state;
HANDLE hRead;
HANDLE hWrite;
HANDLE hsynchronizedWrite;
CircleBuffer buffer;
} RWLock;
class InterProcessCommunication{
public :
InterProcessCommunication():m_bCreator(false){};
~InterProcessCommunication(){
UnLock();
if(m_bCreator)
{
if(pRwLock!=NULL) UnmapViewOfFile(pRwLock);
if(hMap!=NULL) CloseHandle(hMap);
}
};
bool InitializeLock(const char* name);
//阻塞模式
std::string PopString();
void PushString(const char* buff);
private :
RWLock* pRwLock;
bool m_bCreator;
HANDLE hMap;
bool bufferPop(unsigned char* ch);
void bufferPush(unsigned char ch);
void ReadLock();
void WriteLock();
void UnLock();
HANDLE hCondition;
};
#include "stdafx.h"
#include "InterProcessCommunication.h"
#include
enum
{
STATE_EMPTY = 0,
STATE_READ,
STATE_WRITE
};
std::string InterProcessCommunication::PopString()
{
std::string buff;
unsigned char ch;
char* l=new char[256];
char* str=l;
do{
bufferPop(&ch);
*str++=(char)ch;
}while(ch!='\0');
buff=std::string(l);
if(l!=NULL)
delete[] l;
l=NULL;
return buff;
}
void InterProcessCommunication::PushString(const char* buff)
{
unsigned char* str=(unsigned char*)buff;
int len=strlen(buff);
//必须使用同步锁,否则异步写入缓冲区会造成读取顺序混乱
WaitForSingleObject(pRwLock->hsynchronizedWrite,INFINITE);
for(int i=0;i'\0');
ReleaseMutex(pRwLock->hsynchronizedWrite);
}
bool InterProcessCommunication::InitializeLock(const char* name)
{
std::string sharedMemoryName="shared_memory"+std::string(name);
std::string readHandleName="read"+std::string(name);
std::string writeHandleName="write"+std::string(name);
std::string eventLockName="eventLockName"+std::string(name);
std::string synchronizedWrite="synchronizedWrite"+std::string(name);
hMap = ::OpenFileMappingA( FILE_MAP_WRITE, false, sharedMemoryName.c_str());
//TODO 这地方的实现不是很优雅
if ( hMap == NULL )
{
int iErrCode = GetLastError();
hMap=::CreateFileMappingA((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(RWLock),sharedMemoryName.c_str());
if (hMap == 0 )
{
int iErrCode = GetLastError();
return false ;
}
m_bCreator=true;
}
RWLock* _pRwLock = (RWLock*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
HANDLE hRead=OpenMutexA(NULL,false,readHandleName.c_str());
if(hRead==NULL)
{
hRead=CreateMutexA(NULL,false,readHandleName.c_str());
if(hRead==NULL) return false;
}
HANDLE hWrite=OpenMutexA(NULL,false,writeHandleName.c_str());
if(hWrite==NULL)
{
hWrite=CreateMutexA(NULL,false,writeHandleName.c_str());
if(hWrite==NULL) return false;
}
hCondition=OpenEventA(EVENT_ALL_ACCESS ,NULL,eventLockName.c_str());
if(hCondition==NULL)
{
hCondition=CreateEventA(NULL,false,false,eventLockName.c_str());
if(hCondition==NULL) return false;
}
HANDLE hsynchronizedWrite=OpenMutexA(NULL,false,synchronizedWrite.c_str());
if(hsynchronizedWrite==NULL)
{
hsynchronizedWrite=CreateMutexA(NULL,false,synchronizedWrite.c_str());
if(hsynchronizedWrite==NULL) return false;
}
_pRwLock->hsynchronizedWrite=hsynchronizedWrite;
_pRwLock->hRead = hRead;
_pRwLock->hWrite = hWrite;
if(m_bCreator)
{
_pRwLock->count = 0;
}
_pRwLock->state = STATE_EMPTY;
pRwLock=_pRwLock;
return true;
}
void InterProcessCommunication::ReadLock()
{
assert(NULL != pRwLock);
WaitForSingleObject(pRwLock->hRead, INFINITE);
pRwLock->count ++;
if(1 == pRwLock->count){
WaitForSingleObject(pRwLock->hWrite, INFINITE);
pRwLock->state = STATE_READ;
}
ReleaseMutex(pRwLock->hRead);
}
void InterProcessCommunication::WriteLock()
{
assert(NULL != pRwLock);
WaitForSingleObject(pRwLock->hWrite, INFINITE);
pRwLock->state = STATE_WRITE;
}
void InterProcessCommunication::UnLock()
{
assert(NULL != pRwLock);
if(STATE_READ == pRwLock->state){
WaitForSingleObject(pRwLock->hRead, INFINITE);
pRwLock->count--;
if(0 == pRwLock->count){
pRwLock->state = STATE_EMPTY;
ReleaseMutex(pRwLock->hWrite);
}
ReleaseMutex(pRwLock->hRead);
}else{
pRwLock->state = STATE_EMPTY;
ReleaseMutex(pRwLock->hWrite);
}
return;
}
bool InterProcessCommunication::bufferPop(unsigned char* _buf)
{
label1:
if(pRwLock->buffer.head_pos==pRwLock->buffer.tail_pos)
{
WaitForSingleObject(hCondition, 500);
ResetEvent(hCondition);
goto label1;
}
else
{
*_buf=pRwLock->buffer.circle_buffer[pRwLock->buffer.head_pos];
ReadLock();
if(++pRwLock->buffer.head_pos>=BUFFER_MAX)
pRwLock->buffer.head_pos=0;
UnLock();
return true;
}
}
void InterProcessCommunication::bufferPush(unsigned char _buf)
{
pRwLock->buffer.circle_buffer[pRwLock->buffer.tail_pos]=_buf;
WriteLock();
if(++pRwLock->buffer.tail_pos>=BUFFER_MAX)
pRwLock->buffer.tail_pos=0;
//缓冲区数据满后,尾指针与头指针指向同一个地方,原数据被覆盖 头指针向前移动
if(pRwLock->buffer.tail_pos==pRwLock->buffer.head_pos)
if(++pRwLock->buffer.head_pos>=BUFFER_MAX)
pRwLock->buffer.head_pos=0;
UnLock();
SetEvent(hCondition);
}