在 Windows 平台,記憶體對應檔案 是實現進程間高速資料共享的首選方案。核心優勢在於:
HANDLE GetShare(char* &ShareP, int size, char* ShareName) {
// 建立/開啟分頁檔對應物件
// (HANDLE)-1 表示使用系統分頁檔,不關聯實體檔案
HANDLE fh = CreateFileMapping(
(HANDLE)-1, // 使用系統分頁檔
NULL, // 預設安全性
PAGE_READWRITE, // 讀寫權限
0, size, // 大小 (高/低 32 位元)
ShareName // 共享名稱 (全域命名空間)
);
// 映射視圖至進程位址空間
ShareP = (char*)MapViewOfFile(fh, FILE_MAP_ALL_ACCESS, 0, 0, 0);
// 首次建立時初始化為零
if (GetLastError() != ERROR_ALREADY_EXISTS) {
ZeroMemory(ShareP, size);
}
return fh;
}
char* ShareP = NULL;
void test() {
HANDLE fh = GetShare(ShareP, 128, "ShareForMyProg");
for (int i = 0; i < 128; i++) {
ShareP[i] = i; // 寫入測試資料
}
CloseHandle(fh); // 關閉控制代碼 (映射視圖保持有效直到 UnmapViewOfFile)
}
struct SharedData {
volatile LONG sequence; // 序號,用於讀寫同步
DWORD timestamp; // 時間戳
char payload[1024]; // 實際資料
CRITICAL_SECTION cs; // 進程間關鍵區 (需初始化為共享)
};
// 初始化關鍵區 (僅建立者執行)
InitializeCriticalSectionAndSpinCount(&shared->cs, 0x80000000); // 設定互斥體屬性
struct RingBuffer {
volatile LONG head, tail; // 原子操作索引
char buffer[65536]; // 64KB 緩衝區
// 無鎖寫入範例
bool push(const char* data, int len) {
LONG next = (head + 1) % sizeof(buffer);
if (next == tail) return false; // 滿
memcpy(buffer + head, data, len);
InterlockedExchange(&head, next);
return true;
}
};
共享記憶體本身不提供同步,必須搭配:
| 陷阱 | 解決方案 |
|---|---|
| 指標在進程間無效 | 僅共享偏移量或索引,勿直接儲存/傳遞指標 |
| 32/64 位元指標大小不一 | 使用固定大小型別 (int32_t, int64_t) 或相對偏移 |
| 未同步導致資料競爭 | 必要時使用 Interlocked* 原子操作或關鍵區/互斥體 |
| 進程異常終止留下殘留物件 | 啟動時檢查 `ERROR_ALREADY_EXISTS` 並驗證資料完整性 |
| 記憶體洩漏 | 確保 `UnmapViewOfFile` 與 `CloseHandle` 配對呼叫 |
共享記憶體透過 `CreateFileMapping`/`MapViewOfFile` 實現進程間零複製資料交換,是高效能 IPC 的核心技術。配合命名空間管理、安全性描述元、同步物件,可構建穩健的跨進程資料共享架構。開發時務必注意指標有效性、位元寬度相容、同步正確性與資源釋放,確保系統穩定與安全。