Win32 架構下每個進程擁有獨立 4GB 虛擬位址空間,進程間無法直接存取彼此記憶體。本文系統整理 Windows 95/NT 時代確立、至今仍是核心的四大 IPC 機制:記憶體映射檔、共享資料區 DLL、WM_COPYDATA 訊息、ReadProcessMemory/WriteProcessMemory,並輔以同步物件與視窗訊息通知的工程實踐模式。
核心 API:CreateFileMapping、MapViewOfFile、OpenFileMapping、UnmapViewOfFile、CloseHandle。
HANDLE hMap = CreateFileMapping(
(HANDLE)0xFFFFFFFF, // INVALID_HANDLE_VALUE:使用分頁檔
NULL, // 預設安全性
PAGE_READWRITE, // 保護屬性
0, 0x1000, // 大小 4KB
_T("MySharedMem") // 名稱,跨進程可見
);
LPVOID pView = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
// 寫入資料...
// 同步:建立 Mutex/Event 通知 Reader
HANDLE hMap = OpenFileMapping(FILE_MAP_READ, FALSE, _T("MySharedMem"));
LPVOID pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
// 讀取資料...
UnmapViewOfFile(pView);
CloseHandle(hMap);
PAGE_WRITECOPY 可實現 Copy-on-Write,保護原始資料MapViewOfFile 指定 dwOffset/dwNumberOfBytesToMap利用 #pragma data_seg 建立具名區段,.def 設定 SHARED 屬性。
// Shared.h
#pragma data_seg("MYSHARED")
__declspec(dllexport) char g_szBuffer[4096] = {0};
#pragma data_seg()
#pragma comment(linker, "/SECTION:MYSHARED,RWS") // RWS = Read Write Shared
缺點:每個進程載入時會獲得私有複本(Copy-on-Write),寫入不會反映到其他進程。真正共享需在 .def 明確 SECTIONS MYSHARED READ WRITE SHARED,但此機制在現代 Windows(ASLR、DEP、Session 隔離)下可靠性下降,不建議新專案使用。
專為「發送端不修改資料、接收端同步處理」設計。
// 發送端
COPYDATASTRUCT cds;
cds.dwData = 123; // 自訂標識
cds.cbData = strlen(szText)+1; // 含結尾 null
cds.lpData = (PVOID)szText;
SendMessage(hwndTarget, WM_COPYDATA, (WPARAM)hwndSelf, (LPARAM)&cds);
// 接收端(視窗程序)
case WM_COPYDATA:
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
// 處理 pcds->lpData,長度 pcds->cbData
return TRUE;
SendMessage 同步阻塞,確保資料在回傳前不被釋放ChangeWindowMessageFilterEx需 PROCESS_VM_READ/PROCESS_VM_WRITE/PROCESS_VM_OPERATION 權限,通常用於除錯器、外掛、反作弊,一般應用極少直接使用。
HANDLE hProc = OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,
FALSE, dwTargetPID);
if (hProc) {
ReadProcessMemory(hProc, lpBaseAddr, localBuf, size, &bytesRead);
WriteProcessMemory(hProc, lpBaseAddr, localBuf, size, &bytesWritten);
CloseHandle(hProc);
}
風險:目標進程記憶體佈局不穩定(ASLR)、存取違例導致雙方崩潰、安全軟體攔截。嚴禁用於常規資料交換。
無論採用哪種資料通道,同步通知都是必需環節:
CreateMutex(NULL, FALSE, _T("Global\\MyAppSync"))UINT WM_MYNOTIFY = RegisterWindowMessage(_T("MyAppNotify")),配合 FindWindow/PostMessage 通知| 場景 | 推薦技術 | 理由 |
|---|---|---|
| 本機大資料高頻共享 | Memory Mapped File + Mutex | 零拷貝、核心支援、跨語言 |
| 本機小資料/事件通知 | WM_COPYDATA / RegisterWindowMessage | 簡單、視窗模型天然同步 |
| 跨網路/跨機器 | Named Pipe / TCP Socket / gRPC | 透明擴充至分散式 |
| Managed 代碼互操作 | MemoryMappedFile / NamedPipe / WCF | .NET 原生封裝、安全 |