|
다중 프로세스간 공유메모리를 사용하려고 합니다.
빌더포럼의 FAQ에서 에보니님이 올려주신 소스로 SharedData.dll파일을
만든 뒤 2개의 Process에서 공유메모리에 접근하여 정보를 공유하려고 합니다.
현재 SharedData.dll은 에러없이 생성되었으며, 하나의 프로세스에서 공유메모리를
쓰는데는 문제 없으나 또하나의 프로세스를 실행시키면 문제가 발생됩니다.
SharedData.dll소스를 보면 SharedDataCount변수를 이용하여 이미 공유메모리가 생성되어 있으면
기존의 공유메모리를 Open하여 사용해야 하는데, 저는 두번째 프로세스를 실행시키면 처음과 똑같이
다시 공유 메모리를 할당합니다.
그리고 두 프로세스가 각각 공유메모리에 정보를 저장하면 숫자데이타는 읽기/쓰기가 문제 없으나
문자데이터는 저장이 안됩니다.
( 두개의 각 프로그램은 동일 코드로 작성하였습니다. )
아무래도 놓치는 부분이 있는것 같은데... 먼지 모르겠네요 ㅡ.ㅡ
고수님의 조언부탁드립니다...
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 1. 각 프로그램 소스
//---------------------------------------------------------------------------
#include <vcl.h>
#include <SysUtils.hpp>
#pragma hdrstop
#include "One.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
// 공유메모리에 올라가 있는 구조체 정보를 가져와서 EditBox에 뿌린다.
pData = GetSharedData();
Edit1->Text = IntToStr(pData->iData);
Edit2->Text = pData->cString;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// 구조체에 정보를 저장한 뒤 공유 메모리에 올린다.
pData->iData = 1;
pData->cString = "Process1";
SetSharedData(pData);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShowMessage(IntToStr(GetSharedDataCount()));
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// 2. SharedData.dll 소스
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
// Important note about DLL memory management when your DLL uses the
// static version of the RunTime Library:
//
// If your DLL exports any functions that pass String objects (or structs/
// classes containing nested Strings) as parameter or function results,
// you will need to add the library MEMMGR.LIB to both the DLL project and
// any other projects that use the DLL. You will also need to use MEMMGR.LIB
// if any other projects which use the DLL will be performing new or delete
// operations on any non-TObject-derived classes which are exported from the
// DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
// EXE's to use the BORLNDMM.DLL as their memory manager. In these cases,
// the file BORLNDMM.DLL should be deployed along with your DLL.
//
// To avoid using BORLNDMM.DLL, pass string information using "char *" or
// ShortString parameters.
//
// If your DLL uses the dynamic version of the RTL, you do not need to
// explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------
/******************************************************************************
DLL 내부의 함수 조율 지시자.
******************************************************************************/
#ifdef __DLL__
#define DLL_FUNC __declspec(dllexport)
#else
#define DLL_FUNC __declspec(dllimport)
#endif
#include "SharedData.h"
#pragma data_seg(".Shared") // <--- 착한 꼬마가 프로세스 여럿을 대접하게 한다... =ㅅ=;;
TSharedData *SharedData = NULL;
int SharedDataCount = 0;
#pragma data_seg()
HANDLE MapHandle;
/*****************************************************************************
익스포트할 함수들.
*****************************************************************************/
extern "C" __declspec(dllexport) void __stdcall SetSharedData(TSharedData *ASharedData);
extern "C" __declspec(dllexport) TSharedData *__stdcall GetSharedData();
extern "C" __declspec(dllexport) int __stdcall GetSharedDataCount();
#pragma argsused
// 데이터가 저장된 구조체를 리턴한다.
TSharedData *__stdcall GetSharedData()
{
ShowMessage(IntToStr(SharedData->iData));
ShowMessage(SharedData->cString);
return SharedData;
}
// 전달받은 구조체를 기존의 구조체에 저장한다.
void __stdcall SetSharedData(TSharedData *ASharedData)
{
SharedData = ASharedData;
}
//
int __stdcall GetSharedDataCount()
{
return SharedDataCount;
}
// 메모리 맵을 생성한다.
void CreateSharedData()
{
int size = sizeof(TSharedData); // 구조체 공간만큼 할당
// 공유 메모리를 설정한 뒤, 메모리에 대한 핸들값을 갖는다.
MapHandle = CreateFileMapping((HANDLE)0xFFFFFFFF, // 핸들값 정의
NULL,
PAGE_READWRITE,
0, // 메모리 공간 크기(High)
size, // 메모리 공간 크기(Low)
MMFileName); // 공유 메모리 이름 설정
if ( MapHandle == NULL ) // 할당 실패하면
{
ShowMessage("Unable to create file mapping !");
return;
}
// 할당된 공유메모리에 있는 내용을 TShareData으로 케스팅하여 념겨준다.
// MapViewOfFile은 Shared Memory의 Starting Address값을 리턴한다.
SharedData = (TSharedData *)MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, size);
if ( SharedData == NULL )
{
CloseHandle(MapHandle);
ShowMessage("Unable to map view of file. Error : " + GetLastError());
}
}
// 메모리 맵에 매핑된 공유 데이터를 연다.
void OpenSharedData()
{
int size = sizeof(TSharedData);
// MMFileName으로 생성된 공유메모리의 핸들을 가져온다.
MapHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, MMFileName);
if ( MapHandle == NULL )
{
ShowMessage("Unable to Open file mapping !");
return;
}
SharedData = (TSharedData *)MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, size);
if ( SharedData == NULL )
{
CloseHandle(MapHandle);
ShowMessage("Unable to map view of file. Error : " + GetLastError());
}
}
// 공유된 메모리맵과 핸들을 닫는다.
void CloseSharedData()
{
UnmapViewOfFile(SharedData);
CloseHandle(MapHandle);
}
// 공유된 메모리맵의 데이터를 초기화 한다.
void InitSharedData()
{
SharedData->iData = 0;
SharedData->cString = "Initial";
}
//---------------------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH : // 프로세스가 이 DLL을 자기 공간으로 매핑할 때
if ( SharedDataCount == 0 ) // 대신 CreateFileMapping 의 에러 반환 값인
{ // ERROR_ALREADY_EXIST 를 이용 가지를 쳐도 상관엄따....
ShowMessage("Mapping Create");
CreateSharedData(); // Win32 DLL 의 특성상 자체 레퍼런스 카운트가 있으나
SharedDataCount ++; // 이해를 돕기위해 채택... =ㅅ=;;
InitSharedData();
}
else
{
ShowMessage("Mapping Open");
OpenSharedData();
SharedDataCount ++;
}
break;
case DLL_PROCESS_DETACH : // 프로세스가 이 DLL을 자기 주소 공간에서 언맵할 때
ShowMessage("Unmapping Start");
CloseSharedData();
SharedDataCount --;
break;
}
return true;
}
//---------------------------------------------------------------------------
|