在 Windows 系統中,進程擁有獨立的虛擬地址空間,無法直接共享記憶體。為了實現數據交換與協作,必須借助核心物件或系統提供的通訊機制。本文將深入剖析 WM_COPYDATA 訊息機制,並系統梳理 Windows 下主流的十種進程間通訊方式,幫助開發者根據場景選擇最佳方案。
WM_COPYDATA 是 Win32 API 中專為進程間數據傳輸設計的標準訊息。它允許發送進程將任意二進制數據安全地複製到接收進程的地址空間中。
typedef struct tagCOPYDATASTRUCT {
DWORD dwData; // 32 位自定義數據,可用於標識數據類型
DWORD cbData; // lpData 指向的數據大小(位元組數)
PVOID lpData; // 指向實際數據的指標
} COPYDATASTRUCT;
推薦使用 SendMessage 而非 PostMessage,因為 SendMessage 是同步阻塞的:接收進程處理完訊息並複製數據前,發送進程會一直等待,確保數據在傳輸過程中不被修改或釋放。
LRESULT SendMessage(
HWND hWnd, // 接收進程的視窗句柄
UINT Msg, // WM_COPYDATA
WPARAM wParam, // 發送進程的視窗句柄
LPARAM lParam // 指向 COPYDATASTRUCT 的指標
);
開發時必須注意的三大禁忌:
SendMessage 返回。HDC、HBITMAP 等 GDI 物件句柄,它們在進程邊界外失效。FindWindow(NULL, "接收進程視窗標題") 獲取。在消息映射表中添加 ON_WM_COPYDATA(),並實現處理函數:
BOOL CCanCollectorDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) {
char szBuffer[300];
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "dwData:%d cbData:%d\r\nlpData:0x%08x = %s\r\n\r\n",
pCopyDataStruct->dwData, pCopyDataStruct->cbData,
(PVOID)pCopyDataStruct->lpData, (char*)pCopyDataStruct->lpData);
// 實際業務邏輯處理...
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
以下按適用場景與複雜度分類整理:
CreateFileMapping + MapViewOfFile 建立命名/匿名映射區。最快的 IPC 方式,但必須搭配互斥體等同步物件防止競態條件。分「Peer-to-Peer」(各進程嘗試創建,檢查 ERROR_ALREADY_EXISTS)與「Client/Server」(僅 Server 創建初始化)兩種模式。CWnd 封裝支援,現極少用於程式間通訊。透過 COM/LPT 埠進行硬體級通訊,屬邊緣場景,不再贅述。
從作業系統原理看,進程間通訊本質上可歸納為七大經典模型:
| 模型 | 特點 | 典型應用 |
|---|---|---|
| 管道 | 半雙工、單向、僅限親緣進程 | Shell 管線 ls | grep |
| 有名管道 | 半雙工、無親緣限制 | 本機服務通訊 |
| 信號量 | 計數器、同步/互斥 | 資源池控制 |
| 消息佇列 | 鏈表結構、核心持久化、帶格式 | 異步任務分發 |
| 信號 | 非同步通知、處理複雜 | 進程控制 |
| 共享內存 | 最快、需額外同步機制 | 大數據高頻交換 |
| 套接字 | 跨主機、跨平台、網路標準 | 分散式系統 |
WM_COPYDATA 或命名管道。掌握各機制的優劣與適用邊界,是構建健壯、高效 Windows 應用的關鍵基礎。