zoukankan      html  css  js  c++  java
  • 进程间通信-共享内存

    把之前代码整理下,封装了一个用于共享内存的类。

    头文件:CShareMem.h

     1 /* @CShareMem类用于内存映射文件,在进程间传输帧数据 */
     2 enum eDATATYPE { NONE_TYPE, FRAME_TYPE, STATUS_TYPE, INFO_TYPE, CMD_TYPE };
     3 class CShareMem
     4 {
     5 public:
     6     enum EM_EVENS { EV_NONE, EV_READ_THIS, EV_WRITE_THIS, EV_READ_OTHER, EV_WRITE_OTHER, EV_TIMEOUT };
     7 public: 
     8     struct SM_MEMFLAG
     9     {
    10         enum eMemFlag{ ACT_NONE, ACT_READ, ACT_WRITE } eLastAction;
    11         DWORD dwProcessId; 
    12         eDATATYPE eDataType;
    13         UDPFrameData m_DataHead;
    14         char m_DataBuff[BUFFER_SIZE];        // Text from client to server
    15     }; 
    16     class SM_MEMPTR
    17     {
    18     public: 
    19         ~SM_MEMPTR();
    20         SM_MEMFLAG* m_pMemFlag;
    21     private:
    22         friend class CShareMem;
    23         SM_MEMPTR(CShareMem&, SM_MEMFLAG*, SM_MEMFLAG::eMemFlag);
    24         CShareMem& m_ShareMemory; 
    25     };
    26     //
    27     CShareMem(CONST TCHAR* lpName = RZT_FRAME_RECV);
    28     ~CShareMem();
    29     /* @ 使用这个函数获得内存映射的指针,可用于直接存放或读取数据
    30        @ { std::auto_ptr<SM_MEMPTR> ptr = GetMemptr(SM_MEMFLAG::ACT_READ); use ptr .. }
    31     */
    32     std::auto_ptr<SM_MEMPTR> GetMemptr(SM_MEMFLAG::eMemFlag eFlag)
    33     {
    34         return auto_ptr<SM_MEMPTR>(new SM_MEMPTR(*this, m_pMemFlag,eFlag));
    35     }  
    36     EM_EVENS WaitEvent(DWORD dwTimeOut);
    37     void WaitEvent(EM_EVENS eEvent);
    38     bool Read(UDPFrameData* pDataHead, char* pData, eDATATYPE* type = nullptr);
    39     bool Write(UDPFrameData* pDataHead,const char* pData, eDATATYPE type = FRAME_TYPE);
    40 private:
    41     DWORD m_dwProcessId;
    42     HANDLE m_hMemory;
    43     HANDLE m_hMutex;
    44     HANDLE m_hEvent;
    45     SM_MEMFLAG* m_pMemFlag;
    46     char * m_DataBuff;
    47     UDPFrameData * m_DataHead;
    48 };

    实现文件:CShareMem.cpp

      1 CShareMem::CShareMem(CONST TCHAR* lpName):m_hMemory(NULL), m_hMutex(NULL), m_hEvent(NULL)
      2 { 
      3     m_dwProcessId = GetCurrentProcessId(); 
      4     if (!lpName)
      5     {
      6         lpName = _T("SHARE.MEMORY");
      7     }
      8     m_hMemory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUFFER_SIZE, lpName);
      9     if (::GetLastError() == ERROR_ALREADY_EXISTS)
     10     {
     11         m_hMemory = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, lpName);
     12     }
     13     if (m_hMemory == NULL)
     14     {
     15         ostringstream os;
     16         os << "CreateFileMapping: %s Failed!" << lpName << endl;
     17         LOGFMTE(os.rdbuf()->str().c_str());
     18     }
     19     m_pMemFlag = (SM_MEMFLAG*)::MapViewOfFile(m_hMemory, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(SM_MEMFLAG));
     20     m_DataBuff = m_pMemFlag->m_DataBuff;
     21     m_DataHead = &m_pMemFlag->m_DataHead;
     22     {
     23         TCHAR tcTempName[96] = _T("");
     24         _stprintf_s(tcTempName, _T("%s.Mutex"), lpName);
     25         m_hMutex = ::CreateMutex(NULL, FALSE, tcTempName);
     26         if (m_hMutex == NULL)
     27         {
     28             LOGFMTE(_T("CreateMutex %s Failed"), tcTempName);
     29         }
     30         _stprintf_s(tcTempName, _T("%s.Event"), lpName);
     31         m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, tcTempName);
     32         if (m_hEvent == NULL)
     33         {
     34             LOGFMTE(_T("CreateEvent %s Failed"), tcTempName);
     35         }
     36     }
     37 }
     38 CShareMem::~CShareMem(void)
     39 {
     40     ::UnmapViewOfFile(m_pMemFlag);
     41     ::CloseHandle(m_hMemory);
     42     ::CloseHandle(m_hMutex);
     43     ::CloseHandle(m_hEvent);
     44 }
     45 #define SM_LOCK ::WaitForSingleObject(m_hMutex, INFINITE)
     46 #define SM_UNLOCK ::ReleaseMutex(m_hMutex)
     47 #define SM_SIGNAR ::SetEvent(m_hEvent)
     48 #define SM_RESETEVEN ::ResetEvent(m_hEvent)
     49 CShareMem::SM_MEMPTR::SM_MEMPTR(CShareMem& ShareMemory, SM_MEMFLAG* pMemFlag, SM_MEMFLAG::eMemFlag eFlag)
     50     :m_ShareMemory(ShareMemory)
     51     ,m_pMemFlag(pMemFlag)
     52 { 
     53     ::WaitForSingleObject(m_ShareMemory.m_hMutex, INFINITE);  
     54     m_pMemFlag->dwProcessId = m_ShareMemory.m_dwProcessId;
     55     m_pMemFlag->eLastAction = eFlag;
     56 }
     57 
     58 CShareMem::SM_MEMPTR::~SM_MEMPTR()
     59 { 
     60     ::ReleaseMutex(m_ShareMemory.m_hMutex);
     61     ::SetEvent(m_ShareMemory.m_hEvent);
     62 }
     63 CShareMem::EM_EVENS CShareMem::WaitEvent(DWORD dwTimeOut)
     64 {
     65     DWORD dwState = WaitForSingleObject(m_hEvent, dwTimeOut);
     66     EM_EVENS rtEvent = EV_NONE;
     67     SM_LOCK;
     68     switch (dwState)
     69     {
     70     case WAIT_OBJECT_0:
     71         switch (m_pMemFlag->eLastAction)
     72         {
     73         case SM_MEMFLAG::ACT_READ:
     74             rtEvent = m_pMemFlag->dwProcessId == m_dwProcessId ? EV_READ_THIS : EV_READ_OTHER;
     75             break;
     76         case SM_MEMFLAG::ACT_WRITE:
     77             rtEvent = m_pMemFlag->dwProcessId == m_dwProcessId ? EV_WRITE_THIS : EV_WRITE_OTHER; 
     78             break;
     79         } 
     80         break;
     81     case WAIT_TIMEOUT:
     82         rtEvent = EV_TIMEOUT;
     83         break;
     84     default:
     85         break;
     86     }
     87     SM_UNLOCK;
     88     SM_RESETEVEN;
     89     return rtEvent;
     90 }
     91 
     92 void CShareMem::WaitEvent(EM_EVENS eEvent)
     93 { 
     94     while (WaitEvent(INFINITE) != eEvent);
     95 }
     96 bool CShareMem::Write(UDPFrameData* pDataHead, const char* pData, eDATATYPE type)
     97 {
     98     for (;;)
     99     {
    100         if (m_pMemFlag == NULL)
    101         {
    102             return false;
    103         }
    104         if (m_pMemFlag->eLastAction == SM_MEMFLAG::ACT_WRITE)
    105         {
    106             Sleep(1);
    107         }
    108         else
    109         {
    110             break;
    111         }
    112     }
    113 
    114     SM_LOCK; 
    115     memcpy_s(m_DataHead, HEADER_SIZE, pDataHead, HEADER_SIZE);
    116     memcpy_s(m_DataBuff, pDataHead->m_nFrameSize, pData, pDataHead->m_nFrameSize); 
    117     m_pMemFlag->eDataType = type;
    118     m_pMemFlag->dwProcessId = m_dwProcessId;
    119     m_pMemFlag->eLastAction = SM_MEMFLAG::ACT_WRITE;
    120     SM_SIGNAR;
    121     SM_UNLOCK;
    122     return true;
    123 }
    124 bool CShareMem::Read(UDPFrameData* pDataHead, char* pData, eDATATYPE* type)
    125 {
    126     for(;;)
    127     {
    128         if (m_pMemFlag == NULL)
    129         {
    130             return false;
    131         }
    132         if (m_pMemFlag->eLastAction != SM_MEMFLAG::ACT_WRITE)//
    133         {
    134             Sleep(1);
    135         }
    136         else
    137         {
    138             break;
    139         }
    140     }
    141     SM_LOCK; 
    142     memcpy_s(pDataHead, HEADER_SIZE, m_DataHead, HEADER_SIZE);
    143     memcpy_s(pData, pDataHead->m_nFrameSize, m_DataBuff, pDataHead->m_nFrameSize);
    144     if (type)
    145     {
    146         *type = m_pMemFlag->eDataType;
    147     }
    148     m_pMemFlag->dwProcessId = m_dwProcessId;
    149     m_pMemFlag->eLastAction = SM_MEMFLAG::ACT_READ;
    150     SM_SIGNAR; 
    151     SM_UNLOCK;
    152     return true;
    153 }
  • 相关阅读:
    Android 单元测试
    Android 读取和保存文件(手机内置存储器)
    Android 检查是否安装SD卡
    Android 检测网络是否可用
    Android 获取网络链接类型
    Android 中如何使用动画
    Ubuntu 下对ADT 添加别名(alias)
    Docker 配置固定IP及桥接的实现方法(转载)
    macOS下通过docker在局域网成功访问mysql5.6数据库
    MySQL 8.0 Docker使用注解
  • 原文地址:https://www.cnblogs.com/xuyouzhu/p/8757601.html
Copyright © 2011-2022 走看看