IT_Programming/MFC · API

[API] 메모리 공유

JJun ™ 2009. 9. 7. 20:44

==================================================================================================

 

파일 매핑(Memory Mapped IO)으로 두 프로세스가 메모리를 공유하는 방법

 

                                                                                    참고 : 윈도우즈 API 정복

-----------------------------------------------------------------------------------------------

 

[실행화면]

 : MemShare1에서 키보드 입력을 하는 경우 MemShare2의 에디트 윈도우에도 같이 입력된다.

 

 : MemShare2에서 키보드 입력을 하는 경우 MemShare1의 에디트 윈도우에도 같이 입력된다.

 

-----------------------------------------------------------------------------------------------

 

[소스코드]

 

/* MemShare1.cpp */

#include <windows.h>
#include <windowsx.h>   // 메시지 크래커 사용을 위해 추가

 

#define ID_EDIT   100                    // 에디트 윈도우의 Menu ID 값
#define MAXSHAREMEMORY 1024 // 최대 메모리 공유 사이즈

 

// 윈도우 프로시저 프로토 타입
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

 

// 메시지 크랙커 정의 함수 프로토 타입
BOOL MemShare1_OnCreate(HWND, LPCREATESTRUCT);
void MemShare1_OnCommand(HWND, int, HWND, UINT);
void MemShare1_OnPaint(HWND);
void MemShare1_OnDestroy(HWND);

 

UINT UserMessage; // 사용자 정의 메시지
HWND hEdit;           // 에디트 윈도우
HANDLE hFMap;     // 파일 연결 오브젝트 변수
TCHAR *PtrlnFile;   // 메모리에 매핑의 시작번지를 나타내는 포인터 변수

 

// 윈도우 메인
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,

                                    int nShowCmd)
{
      HWND   hwnd;
      MSG    msg;
      WNDCLASS  wndclass = {0};
      static TCHAR WinMainClassName[] = TEXT("MemShare1");

 

      wndclass.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE);
      wndclass.hInstance  = hInstance;
      wndclass.lpfnWndProc = WndProc;
      wndclass.lpszClassName = WinMainClassName;
      wndclass.style   = CS_HREDRAW | CS_VREDRAW;

      RegisterClass(&wndclass);

 

      hwnd = CreateWindow (
                                          WinMainClassName,
                                          WinMainClassName,
                                          WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          NULL,
                                          (HMENU) NULL,
                                          hInstance,
                                          NULL
                                    );

 

      ShowWindow(hwnd, nShowCmd);

 

      // 메시지 루프
      while(GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

 

      return (int)msg.wParam;
}

 

// 윈도우 프로시저 구현
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
      switch (iMessage) // 메시지 크랙커
      {
            HANDLE_MSG(hwnd, WM_CREATE,   MemShare1_OnCreate);
            HANDLE_MSG(hwnd, WM_COMMAND,  MemShare1_OnCommand);
            HANDLE_MSG(hwnd, WM_PAINT,   MemShare1_OnPaint);
            HANDLE_MSG(hwnd, WM_DESTROY,  MemShare1_OnDestroy);
      }

 

      if(iMessage == UserMessage) // 사용자 정의 메시지
            SetWindowText(hEdit, PtrlnFile);

 

      return (DefWindowProc(hwnd, iMessage, wParam, lParam));
}

 

// 메시지 크랙커 정의 함수 구현
BOOL MemShare1_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
      MoveWindow(hwnd, 80, 200, 400, 350, TRUE);

      hEdit = CreateWindow(
                                          TEXT("edit"),
                                          NULL,
                                          WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE,
                                          10, 10, 500, 200,
                                          hwnd,
                                          (HMENU) ID_EDIT,
                                          GetModuleHandle(0),
                                          NULL
                                    );
 
      // 사용자 정의 메시지 등록!
      UserMessage = RegisterWindowMessage(TEXT("WM_SYNCSHAREMEMORY"));

     

      // 파일 연결 오브젝트 생성!
      hFMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,    

                                                    MAXSHAREMEMORY, "MEMORYSHAREMAPPING");
 
      // 파일뷰를 메모리에 매핑!
      PtrlnFile = (TCHAR *) MapViewOfFile(hFMap, FILE_MAP_ALL_ACCESS, 0, 0,

                                                              MAXSHAREMEMORY);

     

      return TRUE;
}

 

void MemShare1_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
      switch(id)     // LOWORD(wParam)
      {
           case ID_EDIT :
                 switch(codeNotify)  // HIWORD(wParam)
                 {
                      case EN_CHANGE :
                       {
                             HWND hTarget; 
                             GetWindowText(hEdit, PtrlnFile, MAXSHAREMEMORY);
                             hTarget = FindWindow(NULL, TEXT("MemShare2")); // 찾을 윈도우

                         

                             if(hTarget)
                                   SendMessage(hTarget, UserMessage, 0, 0);

                       }
                       break;
                 }
      }
}

 

void MemShare1_OnPaint(HWND hwnd)
{
      PAINTSTRUCT ps;
      TCHAR  *Message = TEXT("메모리 공유 테스트");
      HDC   hdc = BeginPaint(hwnd, &ps);
      TextOut(hdc, 10, 220, Message, lstrlen(Message));
      EndPaint(hwnd, &ps);
}

 

void MemShare1_OnDestroy(HWND hwnd)
{
      // Memory Mapped File 관련 자원 해제
      UnmapViewOfFile(PtrlnFile);
      CloseHandle(hFMap);

 

      PostQuitMessage(0);
}

 

-----------------------------------------------------------------------------------------------

 

/* MemShare2.cpp */

#include <windows.h>
#include <windowsx.h>   // 메시지 크래커 사용을 위해 추가

 

#define ID_EDIT   100                      // 에디트 윈도우의 Menu ID 값
#define MAXSHAREMEMORY 1024   // 최대 메모리 공유 사이즈

 

// 윈도우 프로시저 프로토 타입
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

 

// 메시지 크랙커 정의 함수 프로토 타입
BOOL MemShare2_OnCreate(HWND, LPCREATESTRUCT);
void MemShare2_OnCommand(HWND, int, HWND, UINT);
void MemShare2_OnPaint(HWND);
void MemShare2_OnDestroy(HWND);

 

UINT UserMessage; // 사용자 정의 메시지
HWND hEdit;            // 에디트 윈도우
HANDLE hFMap;      // 파일 연결 오브젝트 변수
TCHAR *PtrlnFile;     // 메모리에 매핑의 시작번지를 나타내는 포인터 변수

 

// 윈도우 메인
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,

                                    int nShowCmd)
{
      HWND   hwnd;
      MSG    msg;
      WNDCLASS  wndclass = {0};
      static TCHAR WinMainClassName[] = TEXT("MemShare2");

 

      wndclass.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE);
      wndclass.hInstance  = hInstance;
      wndclass.lpfnWndProc = WndProc;
      wndclass.lpszClassName = WinMainClassName;
      wndclass.style   = CS_HREDRAW | CS_VREDRAW;

      RegisterClass(&wndclass);

 

      hwnd = CreateWindow (
                                          WinMainClassName,
                                          WinMainClassName,
                                          WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,       

                                          CW_USEDEFAULT,
                                          NULL,
                                          (HMENU) NULL,
                                          hInstance,
                                          NULL
                                    );

 

      ShowWindow(hwnd, nShowCmd);

 

      // 메시지 루프
      while(GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

 

      return (int)msg.wParam;
}

 

// 윈도우 프로시저 구현
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
      switch (iMessage) // 메시지 크랙커
      {
            HANDLE_MSG(hwnd, WM_CREATE,   MemShare2_OnCreate);
            HANDLE_MSG(hwnd, WM_COMMAND,  MemShare2_OnCommand);
            HANDLE_MSG(hwnd, WM_PAINT,   MemShare2_OnPaint);
            HANDLE_MSG(hwnd, WM_DESTROY,  MemShare2_OnDestroy);
      }

     

      if(iMessage == UserMessage) // 사용자 정의 메시지
            SetWindowText(hEdit, PtrlnFile);

 

      return (DefWindowProc(hwnd, iMessage, wParam, lParam));
}

 

// 메시지 크랙커 정의 함수 구현
BOOL MemShare2_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
      MoveWindow(hwnd, 500, 200, 400, 350, TRUE);

      hEdit = CreateWindow(
                                          TEXT("edit"),
                                          NULL,
                                          WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE,
                                          10, 10, 500, 200,
                                          hwnd,
                                          (HMENU) ID_EDIT,
                                          GetModuleHandle(0),
                                          NULL
                                    );

 

      // 사용자 정의 메시지 등록!
      UserMessage = RegisterWindowMessage(TEXT("WM_SYNCSHAREMEMORY"));

 

      // 파일 연결 오브젝트 생성!
      hFMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,     

                                                  MAXSHAREMEMORY, "MEMORYSHAREMAPPING");

 

      // 파일뷰를 메모리에 매핑!
      PtrlnFile = (TCHAR *) MapViewOfFile(hFMap, FILE_MAP_ALL_ACCESS, 0, 0,

                                                            MAXSHAREMEMORY);

 

      return TRUE;
}

 

void MemShare2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
      switch(id) // LOWORD(wParam)
      {
           case ID_EDIT :
                 switch(codeNotify) // HIWORD(wParam)
                 {
                      case EN_CHANGE :
                      {
                             HWND hTarget; 
                             GetWindowText(hEdit, PtrlnFile, MAXSHAREMEMORY);
                             hTarget = FindWindow(NULL, TEXT("MemShare1")); // 찾을 윈도우

     

                             if(hTarget)
                                   SendMessage(hTarget, UserMessage, 0, 0);

                       }
                       break;
                 }
      }
}

 

void MemShare2_OnPaint(HWND hwnd)
{
      PAINTSTRUCT ps;
      TCHAR  *Message = TEXT("메모리 공유 테스트");
      HDC   hdc = BeginPaint(hwnd, &ps);
      TextOut(hdc, 10, 220, Message, lstrlen(Message));
      EndPaint(hwnd, &ps);
}

 

void MemShare2_OnDestroy(HWND hwnd)
{
      // Memory Mapped File 관련 자원 해제
      UnmapViewOfFile(PtrlnFile);
      CloseHandle(hFMap);

 

      PostQuitMessage(0);
}

 

==================================================================================================