首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

共享記憶體封裝類 CSFMServer/CSFMClient:跨進程資料交換利器

     編輯:關於VC++

設計目標

簡化 Windows 共享記憶體(Memory Mapped File)的使用,提供 Server/Client 雙模式 封裝,適合「懶人程式設計師」快速整合跨進程通訊功能。

核心類別架構

類別角色關鍵方法
CSFMServer建立/擁有共享記憶體Create(), GetBuffer(), GetSize()
CSFMClient開啟/存取既有共享記憶體Open(), GetBuffer(), GetSize()

使用流程

Server 端:建立共享記憶體

// 建立名為 "_ZZZ_OBJ_"、大小 1 byte 的共享記憶體
CSFMServer m_SFMS;
m_SFMS.Create(NULL, "_ZZZ_OBJ_", 1);  // NULL = 系統分頁檔,不建立實體檔

// 寫入資料
char* p = (char*)m_SFMS.GetBuffer();
if (p) strcpy(p, "1234567890");

Client 端:開啟共享記憶體

// 以讀寫權限開啟同名共享記憶體
CSFMClient* pCSFMC = new CSFMClient(FILE_MAP_READ | FILE_MAP_WRITE, "_ZZZ_OBJ_");

// 讀取/寫入資料
char* p = (char*)pCSFMC->GetBuffer();
if (p) strcpy(p, "1234567890");

關鍵實作細節 (SFMMem.h/.cpp)

複製策略模板

// VARIANT 從介面指標複製
template <typename T>
struct _CopyVariantFromAdaptItf {
    static HRESULT copy(VARIANT* p1, const CAdapt<CComPtr<T>>& p2) {
        HRESULT hr = p2.m_T->QueryInterface(IID_IDispatch, (void**)&p1->pdispVal);
        if (SUCCEEDED(hr)) { p1->vt = VT_DISPATCH; }
        else {
            hr = p2.m_T->QueryInterface(IID_IUnknown, (void**)&p1->punkVal);
            if (SUCCEEDED(hr)) p1->vt = VT_UNKNOWN;
        }
        return hr;
    }
    static void init(VARIANT* p) { VariantInit(p); }
    static void destroy(VARIANT* p) { VariantClear(p); }
};

// 介面指標複製 (AddRef/Release)
template <typename T>
struct _CopyItfFromAdaptItf {
    static HRESULT copy(T** p1, const CAdapt<CComPtr<T>>& p2) {
        if (*p1 = p2.m_T) return (*p1)->AddRef(), S_OK;
        return E_POINTER;
    }
    static void init(T** p) {}
    static void destroy(T** p) { if (*p) (*p)->Release(); }
};

CSFMServer 核心實作

void CSFMServer::Create(char* szFileName, char* szMapName, DWORD dwSize) {
    if (m_iCreateFlag) _Destory();
    
    m_pMapName = szMapName ? _strdup(szMapName) : _strdup(DEFAULT_MAPNAME);
    m_dwSize = (dwSize > 0) ? dwSize : DEFAULT_MAPSIZE;
    
    // 建立/開啟檔案映射物件
    if (szFileName) {
        m_hFile = CreateFile(m_pFileName, GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
                            OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    } else {
        m_hFile = (HANDLE)0xFFFFFFFF;  // 使用系統分頁檔
    }
    
    m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE,
                                   0, m_dwSize, m_pMapName);
    
    m_lpFileMapBuffer = MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS,
                                      0, 0, m_dwSize);
    m_iCreateFlag = 1;
}

CSFMClient 核心實作

void CSFMClient::Open(DWORD dwAccess, char* szMapName) {
    if (m_iOpenFlag) _Destory();
    m_pMapName = szMapName ? _strdup(szMapName) : _strdup(DEFAULT_MAPNAME);
    
    m_hFileMap = OpenFileMapping(dwAccess, TRUE, m_pMapName);
    if (m_hFileMap) {
        m_lpFileMapBuffer = MapViewOfFile(m_hFileMap, dwAccess, 0, 0, 0);
    }
    m_iOpenFlag = 1;
}

資源清理 (RAII 模式)

void CSFMServer::_Destory() {
    if (m_lpFileMapBuffer) { UnmapViewOfFile(m_lpFileMapBuffer); m_lpFileMapBuffer = NULL; }
    if (m_hFileMap) { CloseHandle(m_hFileMap); m_hFileMap = NULL; }
    if (m_hFile && m_hFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); m_hFile = NULL; }
    if (m_pFileName) { free(m_pFileName); m_pFileName = NULL; }
    if (m_pMapName) { free(m_pMapName); m_pMapName = NULL; }
    _Init();
}

測試環境與適用性

  • 測試環境:Win2K + VC6 + 一般應用程式
  • 服務程式/ISAPI 等其他應用類型理論上也適用
  • 預設映射大小:64KB (0xFFFF + 1)

優缺點與改進建議

此封裝類大幅降低共享記憶體使用門檻,是進程間通訊 (IPC) 的輕量級選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
優點缺點/限制改進方向
介面極簡單,兩行程式碼完成跨進程共享無同步機制,多進程並發需自行加鎖內建 Critical Section / Mutex 同步
支援檔案映射與系統分頁檔兩種模式Client 端 GetSize() 回傳 0,無法取得大小共享記憶體頭部存放大小資訊
RAII 自動資源管理,防止洩漏缺乏變更通知機制加入事件通知 (CreateEvent + WaitForSingleObject)