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

Win32 進程間通訊:共享內存實現完整指南

     編輯:關於C語言

Windows 共享內存 IPC:文件映射機制詳解

共享內存是 Windows 平台上最高效的進程間通訊 (IPC) 方式,通過將同一物理內存頁映射到不同進程的虛擬地址空間,實現零拷貝數據交換。核心 API 組合:CreateFileMapping + MapViewOfFile + UnmapViewOfFile + CloseHandle。

核心流程四步走

1. 創建/打開文件映射對象 CreateFileMapping

HANDLE hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,  // 使用系統分頁文件,不關聯實體文件
    NULL,                  // 默認安全屬性
    PAGE_READWRITE,        // 讀寫權限
    0,                     // 高位大小 (0)
    BUF_SIZE,              // 低位大小 (共享內存大小,字節)
    szName                 // 共享內存名稱 (全局命名空間)
);
  • INVALID_HANDLE_VALUE:創建「頁面文件映射」,不需實體文件,適合純內存共享。
  • szName:命名共享內存,允許其他進程通過 OpenFileMapping 打開同一對象。
  • 返回 HANDLE,失敗返回 NULL,需 GetLastError() 診斷。

2. 映射視圖到進程地址空間 MapViewOfFile

LPVOID pBuf = MapViewOfFile(
    hMapFile,              // 文件映射句柄
    FILE_MAP_ALL_ACCESS,   // 讀寫權限
    0, 0,                  // 偏移量 (高32位, 低32位)
    BUF_SIZE               // 映射大小 (0 表示全映射)
);
  • 返回進程虛擬地址空間中的基址指針 pBuf,後續直接通過該指針讀寫數據。
  • 同一進程可多次映射同一映射對象的不同區域 (不同偏移)。

3. 數據讀寫 (直接指針操作)

// 寫入 (進程 A)
GetWindowText(hEdit, szSend, BUF_SIZE);
CopyMemory(pBuf, szSend, BUF_SIZE); // 或 memcpy, strcpy

// 讀取 (進程 B)
printf("共享內存內容: %s\n", (char*)pBuf);

同步關鍵:共享內存本身無同步機制,必須配合 Mutex (互斥量)、Event (事件)、Semaphore (信號量) 或 Critical Section (臨界區 - 僅進程內) 實現讀寫同步,否則會發生競態條件。

4. 清理資源

// 進程退出或不再使用時
UnmapViewOfFile(pBuf);  // 取消映射視圖
CloseHandle(hMapFile);  // 關閉映射對象句柄
// 當所有進程都關閉句柄且取消映射後,系統自動釋放物理內存

完整雙進程示例框架

寫入進程 (Writer)

#include 
#include 
#define BUF_SIZE 1024
#define SHARED_NAME "Global\\MySharedMemory"

int main() {
    HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, SHARED_NAME);
    if (!hMap) { printf("CreateFileMapping 失敗: %d\n", GetLastError()); return 1; }
    
    char *pBuf = (char*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
    if (!pBuf) { printf("MapViewOfFile 失敗\n"); CloseHandle(hMap); return 1; }
    
    // 同步對象:創建互斥量
    HANDLE hMutex = CreateMutex(NULL, FALSE, "Global\\MyMutex");
    
    while (1) {
        WaitForSingleObject(hMutex, INFINITE);
        printf("輸入字符串 (quit 退出): ");
        fgets(pBuf, BUF_SIZE, stdin);
        pBuf[strcspn(pBuf, "\n")] = 0; // 去換行
        ReleaseMutex(hMutex);
        if (strcmp(pBuf, "quit") == 0) break;
        Sleep(100);
    }
    
    UnmapViewOfFile(pBuf);
    CloseHandle(hMutex);
    CloseHandle(hMap);
    return 0;
}

讀取進程

// ... 相同的 CreateFileMapping/OpenFileMapping, MapViewOfFile, Mutex ...
while (1) {
    WaitForSingleObject(hMutex, INFINITE);
    if (strlen(pBuf) > 0) {
        printf("讀取到: %s\n", pBuf);
        // 處理數據...
        memset(pBuf, 0, BUF_SIZE); // 清空標誌已讀
    }
    ReleaseMutex(hMutex);
    Sleep(100);
}

關鍵注意事項總結表

項目說明
命名空間建議加 Global\\ 前綴 (需管理員權限) 或 Local\\ (會話隔離),避免衝突
大小限制受限於進程虛擬地址空間 (32位進程 2GB),大數據建議分段映射
同步機制必須 配合 Mutex/Event,否則數據競爭不可控
內存對齊映射地址由系統決定,通常 64KB 對齊,結構體讀寫注意對齊
繼承性子進程默認繼承句柄 (bInheritHandle=TRUE),可通過安全屬性控制
持久性最後一個句柄關閉且視圖取消映射後,數據丟失 (除非映射實體文件)

對比:其他 IPC 方式

方式速度跨進程同步適用場景
共享內存極快 (零拷貝)✅需外部同步大數據高頻交換 (視頻流、共享緩衝區)
命名管道快 (內核緩衝)✅ (跨網絡)內建同步命令流、請求響應、跨機器
Socket中 (協議開銷)✅ (跨網絡)內建同步網絡通信、跨平台
WM_COPYDATA慢 (用戶態拷貝)✅ (GUI 進程)同步發送GUI 進程簡單數據傳遞
COM/RPC中✅框架處理組件化、跨語言、對象模型

總結

Win32 共享內存通過「文件映射對象 + 視圖映射」實現進程間零拷貝數據共享,是高性能 IPC 首選。但必須配合同步對象使用,否則數據一致性無保障。掌握 CreateFileMapping/MapViewOfFile 核心流程、命名空間規範、同步機制選型,是 Windows 系統級開發的核心技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved