共享內存是 Windows 平台上最高效的進程間通訊 (IPC) 方式,通過將同一物理內存頁映射到不同進程的虛擬地址空間,實現零拷貝數據交換。核心 API 組合:CreateFileMapping + MapViewOfFile + UnmapViewOfFile + CloseHandle。
CreateFileMappingHANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // 使用系統分頁文件,不關聯實體文件
NULL, // 默認安全屬性
PAGE_READWRITE, // 讀寫權限
0, // 高位大小 (0)
BUF_SIZE, // 低位大小 (共享內存大小,字節)
szName // 共享內存名稱 (全局命名空間)
);
INVALID_HANDLE_VALUE:創建「頁面文件映射」,不需實體文件,適合純內存共享。szName:命名共享內存,允許其他進程通過 OpenFileMapping 打開同一對象。HANDLE,失敗返回 NULL,需 GetLastError() 診斷。MapViewOfFileLPVOID pBuf = MapViewOfFile(
hMapFile, // 文件映射句柄
FILE_MAP_ALL_ACCESS, // 讀寫權限
0, 0, // 偏移量 (高32位, 低32位)
BUF_SIZE // 映射大小 (0 表示全映射)
);
pBuf,後續直接通過該指針讀寫數據。// 寫入 (進程 A)
GetWindowText(hEdit, szSend, BUF_SIZE);
CopyMemory(pBuf, szSend, BUF_SIZE); // 或 memcpy, strcpy
// 讀取 (進程 B)
printf("共享內存內容: %s\n", (char*)pBuf);
同步關鍵:共享內存本身無同步機制,必須配合 Mutex (互斥量)、Event (事件)、Semaphore (信號量) 或 Critical Section (臨界區 - 僅進程內) 實現讀寫同步,否則會發生競態條件。
// 進程退出或不再使用時 UnmapViewOfFile(pBuf); // 取消映射視圖 CloseHandle(hMapFile); // 關閉映射對象句柄 // 當所有進程都關閉句柄且取消映射後,系統自動釋放物理內存
#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),可通過安全屬性控制 |
| 持久性 | 最後一個句柄關閉且視圖取消映射後,數據丟失 (除非映射實體文件) |
| 方式 | 速度 | 跨進程 | 同步 | 適用場景 |
|---|---|---|---|---|
| 共享內存 | 極快 (零拷貝) | ✅ | 需外部同步 | 大數據高頻交換 (視頻流、共享緩衝區) |
| 命名管道 | 快 (內核緩衝) | ✅ (跨網絡) | 內建同步 | 命令流、請求響應、跨機器 |
| Socket | 中 (協議開銷) | ✅ (跨網絡) | 內建同步 | 網絡通信、跨平台 |
| WM_COPYDATA | 慢 (用戶態拷貝) | ✅ (GUI 進程) | 同步發送 | GUI 進程簡單數據傳遞 |
| COM/RPC | 中 | ✅ | 框架處理 | 組件化、跨語言、對象模型 |
Win32 共享內存通過「文件映射對象 + 視圖映射」實現進程間零拷貝數據共享,是高性能 IPC 首選。但必須配合同步對象使用,否則數據一致性無保障。掌握 CreateFileMapping/MapViewOfFile 核心流程、命名空間規範、同步機制選型,是 Windows 系統級開發的核心技能。