windows高效进程通信之共享内存环形队列字符串读取

使用方式非常简单,需要的进程初始化类调用InitializeLock函数传入相同的字符串即可。可以多个进程使用PushString(),写入缓冲区,只允许一个进程进行调用PopString()读取,读取方面没有写保护锁,非线程安全。构造函数与析构函数看起来似乎不严谨,但不影响使用,有不对的地方望大牛提供指点。

测试代码用于获取通信所需的时间

1. 进程读取缓冲区代码


 #include "stdafx.h"
 #include <iostream>
 #include <thread>
 #include <Windows.h>
 #include <sstream>
 #include <istream>
 #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;
}

2. 进程写入缓冲区代码

#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <string>  
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<<nBeginTime.QuadPart;  
       istringstream is(os.str());  
       is>>ss;  
       t_MultiProcessLock.PushString(ss.c_str());
       std::cout<<nBeginTime.QuadPart<<std::endl;
   }
   return 0;
}

3.头文件

#pragma once
#include <Windows.h>
#include <assert.h>
#include <iostream>
/**
*
*   @Description windows共享内存多进程高效字符串数据传输,进程安全
*  允许多个进程同时写入缓冲区,只允许一个进程进行读取,读取方式为阻塞式
*   @author        kellygod<kellygod95@gmail.com>
*
*/
#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;
};

4.源文件

#include "stdafx.h"
 #include "InterProcessCommunication.h"
 #include <string>
 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<len;i++)
    {
        bufferPush(*str++);
    }
    bufferPush('\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);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值