데브피아 갔다가 좋은 팁이 있길래 소개 합니다.
보통 프로세스간 메모리를 공유는 memory mapped file을 사용하기 위해 CreateFileMapping 같은 걸 사용하는데
ReadProcessMemory 를 이용해서 공유하는 방법을 간단하게 소개 하겠습니다.
memory mapped file 에 비해 장점이라면
주소만으로 큰 데이터 공유가 가능하다? 정도 겠네요
속도는 잘 모르겠어요
먼저 공유할 메모리를 정의하고, 여기서는 구조체를 사용하도록 해보죠
편의상 데이터를 할당하는 쪽을 서버
데이터를 사용하는 쪽을 클라이언트라고 하면
서버쪽 준비사항은
type
TMyRecord = record // 공유할 구조체
data : array [0..8] of char;
i : integer;
d : array[0..16] of char;
end;
PMyRecord = ^TMyRecord;
var
myRecord : PMyRecord;
procedure TForm1.Button1Click(Sender: TObject);
var
dwProcessId : cardinal;
begin
New(myRecord); //구조체 메모리를 할당해주고
myRecord^.data := 'aaaa';
myRecord^.i := 3434;
myRecord^.d := 'cccc';
// ReadProcessMemory 를 이용하기 위해서는 프로세스 아이디하고, 사용할 메모리 주소를 알아야 합니다.
// 간단하게 테스트 하기 위해 Edit 에 넣고 클라이언트에서 그냥 붙혀넣기로 했습니다. 쿨럭 ;;;;
GetWindowThreadProcessId(Handle, dwProcessId );
Edit1.Text := inttostr(dwProcessId); // 서버쪽 프로세스 ID
Edit2.Text := inttohex(integer(myRecord),8); // 공유할 데이터 Address
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// 정말 메모리가 공유 되는지 확인해 보아요
myRecord^.i := myRecord^.i + 1;
end;
이제 클라이언트는 서버의 데이터를 쓰기위해 서버로부터 메모리 주소를 받기만 하면 되겠군요
메모리 주소는 레지스트리나 ini 에 써두면 되겠군요
클라이언트는 이렇게
type
TMyRecord = record
data : array [0..8] of char;
i : integer;
d : array[0..16] of char;
end;
procedure TForm2.GetMemClick(Sender: TObject);
var
m_hProcess : THandle;
myRecord : TMyRecord;
ReadBytes : cardinal;
pid : integer;
ShareMemaddr : pointer;
begin
// 귀찮아서 이리 했으니 양해를 ;;;;
pid := 7608; // 서버측의 Edit1.text 값이 되겠군요
ShareMemaddr := pointer($011A1C70); // 서버측의 Edit2.text 값이 되겠네요
m_hProcess := OpenProcess(PROCESS_VM_READ, FALSE, pid);
if ReadProcessMemory(m_hProcess, ShareMemaddr , @myRecord, sizeof(TMyRecord), ReadBytes) then
begin
button1.Caption := inttostr(ReadBytes);
Caption := myRecord.data + ' ' + inttostr(myrecord.i) + ' ' + myrecord.d;
end
else
ShowMessage('server down');
end;