Shared Memory

摘要
因工作需求用上了「Shared Memory」這個方法,因此特別整理一篇文章備忘,包含了Shard Memory運作原理,各語言的實作範例(C#, C++, Boost C++),以及如何在UE4中應用。

何謂Shared Memory (截錄自黑暗執行緒)
跨 Process溝通有個術語,Interprocess Communictaion(IPC),在 Windows 平台有以下選擇:參考

  • Clipboard 
    程式 A 將内容貼進剪貼簿,程式 B 自剪貼簿取出内容。
  • COM
    OLE複合文件(Compound Document)讓Word文件可以內嵌Excel工作表,點兩下還能叫出 Excel進行編輯, OLE的基礎為 COM元件技術。
  • Data Copy
    程序 A向程式 B依約定的格式内容傳送WM_COPYDATA訊息
  • DDE
    DDE是一種允許不同應用程式交換不同格式資料的通訊協定,可視為剪貼簿的沿伸,除了一次性抛轉,還能持續傳輸資料。(效能相對差,已不建議使用)
  • File Mapping
    File Mapping意指將檔案模擬成 Process中的一塊記憶體,當多個應用程式間透過共用 File Mapping交換資料,稱之為Named Shared Memory,在各種IPC方法中效能最佳,但必須透過Mutex等同步機制防止讀寫衝突。
  • Mailslots
    單向溝通,Mailslot Client送訊息給Mailslot Server,訊息在Server讀取後删除,支援跨機器傳送,還可一對多廣播。(廣播訊息長度限制 400bytes,一對一傳輸時訊息長度則由 Mailslot Server建立時決定)
  • Pipes
    雙向傳輸,分為Anonymous Pipe及Named Pipe。Anonymous Pipe一般用於父程序與子程序間的標準輸入/輸出導向,雙向溝通要建兩條Pipe,不能跨網路且限於有從屬關係的 Process;Named Pipe則可用於任意Process間交換資料,並支援跨網路Process間傳輸。
  • RPC
    Remote Procedure Call(RPC)允許應用程式呼叫其他應用程式提供的函式功能,並可跨網路呼叫。Windows RPC符合 ISO DCE標準,支援跨作業系統系統整合。
  • Windows Sockets
    基於 TCP/IP 或其他網路協定制訂的抽象通訊介面,底層透過網路連線進行資料交換。

Shared Memory是C/C++開發者常用的資料交換方式,故C/C++開發者在Windows平台也常選擇它做為溝通管道。

AccessChk工具 (下載)
可透過AccessChk工具來檢視Windows目前已開啟的MemoryMappedFile。SystemInternals有個AccessChk工具能列出Windows 所有可存取的檔案、資料夾、Registry、物件以及Windows服務。而MemoryMappedFile屬於一種Windows物件。

  1. 下載AccessChk工具
  2. 於同一目錄建立批次檔accesschk_createObjList.bat,此指令能夠列出所有物件並存檔
  3. 以系統管理員身份執行accesschk_createObjList.bat

在其中尋找MemoryMappedFile名稱,若存在可看到類似以下記錄:
\Sessions\1\BaseNamedObjects\[MemoryMappedFileName]
 Type: Section
 Medium Mandatory Level (Default) [No-Write-Up]
 RW NT AUTHORITY\SYSTEM
    SECTION_ALL_ACCESS
 RW DOMAIN\UserName
    SECTION_ALL_ACCESS
 RW DOMAIN\UserName-S-1-5-5-0-954410
    SECTION_ALL_ACCESS

各語言的Shared Memory實作範例


如何在UE4中應用Shared Memory
雖然UE4 API有提供Shared Memory方法(MapNamedSharedMemoryRegion),不過在UE4論壇裡有失敗的例子(Creating shared memory on Windows always fails),我自己嘗試在UE4.18中使用UE4 API也是仍無法正常運作。

最後是參考jgcoded作法,使用Native C++在UE4中實作Windows shared memory來解決。在本文的範例中,分為一支只寫入數值的程式 (C#, using System.IO.MemoryMappedFiles),負責建立MemoryMappedFile,寫入9個double數值,以及一支只接收數值的程式 (UE4, Native C++, include <windows.h>),負責開啟MemoryMappedFile,讀取9個double數值。

Implement shared memory from C# to UE4 (C#)

Implement shared memory from C# to UE4 (UE4)

這個網誌中的熱門文章

Windows10 版本1607後可啟用支援長路徑檔名 (Maximum Path Length Limitation)

標準使用者如何執行需系統管理者權限的程式