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

Win32 進程間通訊(IPC)核心技術總覽:記憶體映射、共享 DLL、WM_COPYDATA、Read/WriteProcessMemory

     編輯:關於C++

Win32 架構下每個進程擁有獨立 4GB 虛擬位址空間,進程間無法直接存取彼此記憶體。本文系統整理 Windows 95/NT 時代確立、至今仍是核心的四大 IPC 機制:記憶體映射檔、共享資料區 DLL、WM_COPYDATA 訊息、ReadProcessMemory/WriteProcessMemory,並輔以同步物件與視窗訊息通知的工程實踐模式。

一、記憶體映射檔——高效大資料共享首選

核心 API:CreateFileMapping、MapViewOfFile、OpenFileMapping、UnmapViewOfFile、CloseHandle。

建立端(Writer)

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

開啟端(Reader)

HANDLE hMap = OpenFileMapping(FILE_MAP_READ, FALSE, _T("MySharedMem"));
LPVOID pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
// 讀取資料...
UnmapViewOfFile(pView);
CloseHandle(hMap);

關鍵點

  • 多進程寫入必須同步(Mutex、Critical Section 跨進程需名稱)
  • PAGE_WRITECOPY 可實現 Copy-on-Write,保護原始資料
  • 大檔案分段映射:MapViewOfFile 指定 dwOffset/dwNumberOfBytesToMap

二、共享資料區 DLL——簡單陣列/結構共享

利用 #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 隔離)下可靠性下降,不建議新專案使用。

三、WM_COPYDATA——唯讀小資料跨進程傳遞

專為「發送端不修改資料、接收端同步處理」設計。

// 發送端
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 同步阻塞,確保資料在回傳前不被釋放
  • 不支援跨權限層級(UIPI)傳遞,Vista+ 需 ChangeWindowMessageFilterEx
  • 適合小型、單向、即時通知(如進度、狀態碼)

四、ReadProcessMemory / WriteProcessMemory——除錯器級存取

需 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)、存取違例導致雙方崩潰、安全軟體攔截。嚴禁用於常規資料交換。

五、進程間同步與通知模式

無論採用哪種資料通道,同步通知都是必需環節:

  • 命名 Mutex/Event/Semaphore:CreateMutex(NULL, FALSE, _T("Global\\MyAppSync"))
  • 註冊視窗訊息:UINT WM_MYNOTIFY = RegisterWindowMessage(_T("MyAppNotify")),配合 FindWindow/PostMessage 通知
  • 完成埠 (IOCP):高併發伺服器端統一調度

六、現代替代方案建議

七、總結

Win32 IPC 四大經典機制各有適用邊界:記憶體映射檔是大資料共享的工業標準;WM_COPYDATA適合 UI 執行緒間輕量通知;共享 DLL因機制脆弱已棄用;Read/WriteProcessMemory屬逆向/除錯領域。現代開發應優先選擇跨平台、高層級抽象(Named Pipe、gRPC、共享記憶體 C++ 封裝庫),降低維護成本與安全風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦技術理由
本機大資料高頻共享Memory Mapped File + Mutex零拷貝、核心支援、跨語言
本機小資料/事件通知WM_COPYDATA / RegisterWindowMessage簡單、視窗模型天然同步
跨網路/跨機器Named Pipe / TCP Socket / gRPC透明擴充至分散式
Managed 代碼互操作MemoryMappedFile / NamedPipe / WCF.NET 原生封裝、安全