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

Delphi 進程間資料共享:記憶體映射檔實作

     編輯:Delphi

問題背景

DLL 載入時會映射到各進程獨立位址空間,全域變數各自獨立,一個進程修改不影響其他進程,無法直接共享資料。解決方案:記憶體映射檔。

原理

在 Win32 位址空間保留一塊記憶體區域,實體儲存可用分頁檔(優於磁碟檔:無需建立/刪除暫存檔,系統自動管理分頁調度)。多進程映射同一映射物件即可共享資料。

完整 DLL 實作碼

library Project1;
uses
  ShareMem, Windows, SysUtils, Classes;

const
  MFileName: PChar = 'ShareData'; // 映射物件名稱

type
  PGlobalDllData = ^TGlobalDllData;
  TGlobalDllData = record
    S: string[50];
    I: Integer;
  end;

var
  GlobalData: PGlobalDllData; // 指向映射檔視圖的全域指標
  MapHandle: THandle;

{ 供外部進程呼叫,取得共享資料指標 }
procedure GetDllData(var AGlobalData: PGlobalDllData); stdcall;
begin
  AGlobalData := GlobalData;
end;

{ 開啟/建立映射檔並映射至進程位址空間 }
procedure OpenThisData;
var Size: Integer;
begin
  Size := SizeOf(TGlobalDllData);
  // 建立映射物件,使用分頁檔 (DWord(-1))
  MapHandle := CreateFileMapping(DWord(-1), nil, PAGE_READWRITE, 0, Size, MFileName);
  if MapHandle = 0 then RaiseLastWin32Error;
  // 映射視圖至進程位址空間,傳回基址(各進程不同)
  GlobalData := MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);
  // 初始化測試資料
  GlobalData^.S := 'TEST';
  GlobalData^.I := 5;
  if GlobalData = nil then begin
    CloseHandle(MapHandle);
    RaiseLastWin32Error;
  end;
end;

{ 釋放資源 }
procedure CloseThisData;
begin
  UnmapViewOfFile(GlobalData);
  CloseHandle(MapHandle);
end;

{ DLL 進入點 }
procedure DllEntryPoint(dwReason: DWORD);
begin
  case dwReason of
    DLL_PROCESS_ATTACH: OpenThisData;  // 進程載入 DLL 時自動呼叫
    DLL_PROCESS_DETACH: CloseThisData; // 進程卸載 DLL 時自動呼叫
  end;
end;

{$R *.res}
exports GetDllData; // 導出供外部呼叫

begin
  DllProc := @DllEntryPoint; // 指定 DLL 進入/離開處理程序
  DllEntryPoint(DLL_PROCESS_ATTACH); // 手動觸發初始化(確保載入即建立映射)
end.

運作機制

  1. 進程 A 載入 DLL → DllEntryPoint 收到 DLL_PROCESS_ATTACH → 呼叫 OpenThisData 建立映射物件「ShareData」並映射視圖,GlobalData 指向該視圖基址。
  2. 進程 B 載入同 DLL → 同樣建立/開啟「ShareData」映射物件,映射至自身位址空間,GlobalData 指向各自基址(不同),但指向同一實體記憶體。
  3. 進程 A 呼叫 GetDllData 取得指標,修改 GlobalData^.I := 10。
  4. 進程 B 呼叫 GetDllData 取得指標,讀取 GlobalData^.I 即見 10,實現共享。
  5. 進程結束 → DLL_PROCESS_DETACH → CloseThisData 解除映射、關閉控制代碼。

關鍵點

  • CreateFileMapping 第一參數 DWord(-1) 表示使用系統分頁檔。
  • PAGE_READWRITE 允許讀寫。
  • MapViewOfFile 回傳各進程私有的虛擬位址,但映射同一實體頁框。
  • 需在專案選項啟用「ShareMem」或手動管理共享記憶體管理器。
  • 編譯通過 Delphi 6 驗證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved