메일슬롯 방식의 IPC  WindowsSystem 

2011/08/03 13:45

복사http://blog.naver.com/kater102/134225491

첨부파일 (2)

IPC(Inter-Process Communication) 란 프로세스간 통신을 의미 합니다.

 

프로세스 간의 통신을 하려면 어떻게 해야될까요??

 

 

 

 

 

 

 

 

(출처:뇌를자극하는윈도우즈시스템프로그래밍)

 

 프로세스 A 와 프로세스 B 가 같은 공간의 메모리를 공유하고 있다면 통신을 하기에 어려운 점이 없을겁니다. 그냥 만나서 주면 되는 것이죠.

 

 하지만 Windows 에서는 프로세스 간의 메모리 공간을 침범할 수 없게 되어있습니다. 시스템의 안정성을 위해서인데요.

 

 MS word 작업시 미디어플레이어 때문에 MS word 가 에러가 나고 IE 때문에 미디어플레이어가 에러가 나는 등의 오류가 생길 수 있는 것이죠.

 

 실제로 이런 일이 있다면 시스템의 안정성에 상당히 영향을 미치기 때문에 Windows에서는 프로세스의 메모리가 독립적으로 생성되어 서로의 공간을 침범할 수 없게 되어있습니다. 아주 프라이버시가 강한 녀석들이죠?

 

 "프로세스들은 자신에게 할당된 메모리 공간 이외에는 접근이 불가능"

 

 메일슬롯 방식의 IPC

 

 그럼 이들 프로세스간에 통신을 하기 위해서는 방법이 필요한데 (편지를 보낸다든지, 소포를 보낸다든지.) 이때 IPC 의 방법중에 총 세 가지의 방법이 있습니다.

 

 그 중 한가지가 이번 포스팅에서 알아볼 메일슬롯(Mail Slot) 입니다.


(출처: 뇌를자극하는윈도우즈시스템프로그래밍)

 

 메일슬롯은 우체통이라고 생각하시면 됩니다.

 

 "데이터를 주고 받기 위해서 프로세스가 우체통을 마련하는 것"

 

 Receiver(수신인) 이 우체통을(메일슬롯) 만들어두고 Sender(발신인) 가 통로(일종의 스트림?)를 통해 메시지를 보내면 되는 것이죠.

 

 직접 만날수없으니 중간 매개체로 메일슬롯(Mail Slot) 을 이용하는 것입니다.

 

 1. Receiver 가 준비해야 할 것

 => 우체통을 만들면 된다.

 HANDLE CreateMailSlot(

       LPCTSTR lpName,----------------------(1)

       DWORD nMaxMessageSize,-------------(2)

       DWORD lReadTimeout,-----------------(3)

       LPSECURITY_ATTRIBUTE lpSecurityAttributes--(4)

);

 If the function fails, the return value is INVALID_HANDLE_VALUE

 

(1) lpName : 생성하는 메일슬롯의 이름을 결정하는 데 사용

  ex) \\computer\mailslot\[path]name

(2) nMaxMessageSize : 메일슬롯의 크기 결정하는 인자. 0이 전달될 경우 시스템이 허용하는 최대 크기

(3) lReadTimeout : 메일슬롯의 데이터를 읽을 때 파일 입,출력 함수인 ReadFile 함수 사용. But 메일슬롯이 비어 있다면 데이터가 채워질때까지 ReadFile 함수는 반환하지 않고 블로킹(Blocking) 상태에 놓인다. 이때

 lReadTimeout 은 최대 블로킹 시간을 밀리세컨드 단위로 지정. 0을 전달하면 메일슬롯에 읽어 들일 데이터가 있든지, 없든지 간에 블로킹 상태 없이 빠져 나와서 다음 단계로 실행.

 MAILSLOT_WAIT_FOREVER 인자 전달할 경우 ReadFile 함수는 읽어 들일 데이터가 존재하게 될 때까지 블로킹 상태 유지

(4) lpSecurityAttributes : 핸들 상속 용도

 

 2. Sender 가 준비해야할 것

 => 데이터를 Receiver 에게 보내는  역할

 통로를 만들때 쓰는 함수인 CreateFile 함수와 보내는 함수 WriteFile 함수 사용.

 

 

 

 첨부한 예제 파일의 프로그램 구성도입니다.

 

명심해야할 점은 메일슬롯은 단방향 통신입니다. 즉, 우체통을 만들어놓고 메시지를 받는다고해서 그 우체통으로 Receiver 가 메시지를 보내봤자 전달이 안된다는 말이죠. 물론 양쪽에다가 우체통을 (메일슬롯을) 만들어놓으면 가능하겠죠?

 

 파일 입출력 함수 세 가지가 나오는데 메일슬롯 관점에서 중요한 부분만 살펴보고 이번 포스팅은 마무리를 하겠습니다.

 

 CreateFile 함수 간략한 예제 및 설명

 

 

ReadFile

 BOOL ReadFile(

     HANDLE hFile, ----------------------(1)

     LPVOID lpBuffer,--------------------(2)

     DWORD nNumverOfBytesToRead,-----(3)

     LPDWORD lpNumberOfByteRead,------(4)

     LPOVERLAPPED lpOverlapped---------(5)

); 

 ReadFile 함수는 메일슬롯에 존재하는 데이터를 읽어 들인다.

(1) hFile : 메일슬롯의 핸들을 인자로 전달

(2) lpBuffer : 읽어 들인 데이터를 저장할 버퍼를 지정하는 용도로 사용

(3) nNumberOfBytesToread : 읽어 들일 데이터의 최대 크기를 지정

(4) lpNumberOFBytesRead : 함수 호출 완료 된 후, 읽어 들인 데이터 크기를 바이트 단위로 얻기 위한 변수를 지정

(5) lpOverlapped : NULL

 

WriteFile

  BOOL WriteFile(

     HANDLE hFile,---------------------(1)

     LPVOID lpBuffer,--------------------(2)

     DWORD nNumverOfBytesToRead,-----(3)

     LPDWORD lpNumberOfByteRead,------(4)

     LPOVERLAPPED lpOverlapped---------(5)

); 

 WriteFile 함수는 메일슬롯으로 데이터를 전송

(1) hFile : 데이터를 읽어들일 파일을 지정

(2) lpBuffer : 전송할 데이터가 저장되어 있는 버퍼 지정

(3) nNumberOfBytesToWrite : 전송할 데이터 크기 지정

(4) lpNumberOfBytesWritten : 함수 호출 완료된 후, 전송된 실제 데이터의 크기를 바이트 단위로 얻기 위한 변수의 주소를 지정

(5) lpOverlapped : NULL

 

 

 이하 파일 입출력 함수는 나중에 파일 IO 부분에서 더 자세하게 다룰것이나 더 궁금하신 분들은 구글링이나 MSDN 검색을 활용해주시길 바랍니다.

 

 감사합니다.

 

 --By Flow


/*
 
http://sosal.tistory.com/
 * made by so_Sal
 */



Windows 08. IPC 프로세스간 통신
예제소스 입니다.
잘 이해가 안되는 부분이 있다면
아래 링크를 참조하세요.
LINK_

======================= Receiver =======================

#include<stdio.h>
#include<tchar.h>
#include<windows.h>

#define SLOT_NAME _T("\\\\.\\mailslot\\Mail")

int _tmain(int argc,TCHAR *argv[]){

 HANDLE hMailSlot;
 TCHAR messageBox[BUFSIZ];
 DWORD bytesRead;

 hMailSlot = CreateMailslot(     //우체통 생성!!
  SLOT_NAME, 0,
  MAILSLOT_WAIT_FOREVER,
  NULL );

 if(hMailSlot == INVALID_HANDLE_VALUE){
  _fputts( _T("Unable to create MailSlot ! \n"), stdout);
  return 1;
 }

 _fputts( _T("=========== Message =========== \n"),stdout);

 while(1){
  if(!ReadFile(hMailSlot, messageBox, BUFSIZ, &bytesRead,NULL)){
   _fputts( _T("Unable to read 1 \n"), stdout);    // 글이 들어올때까지 기다리고
   CloseHandle(hMailSlot);                              // 들어오면 읽어버림
   return 1;
  }

  if(!_tcsncmp(messageBox, _T("EXIT"), 4)){
   _fputts(_T("Good bye ! \n"), stdout);
   break;
  }

  messageBox[bytesRead/sizeof(TCHAR)] = NULL;
  _fputts(_T("Sender :: "),stdout);
  _fputts(messageBox,stdout);            // 읽어버린거 출력!
 }

 CloseHandle(hMailSlot);
 return 0;
}

======================= Sender =======================

#include<stdio.h>
#include<tchar.h>
#include<windows.h>

#define SLOT_NAME _T("\\\\.\\mailslot\\Mail")

int _tmain(int argc,TCHAR *argv[]){

 HANDLE hMailSlot;
 TCHAR message[BUFSIZ];
 DWORD bytesWritten;

 hMailSlot = CreateFile(       // 우체통에 글쓰려구 파일처럼 취급
  SLOT_NAME,GENERIC_WRITE,
  FILE_SHARE_READ,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL
 );

 if(hMailSlot == INVALID_HANDLE_VALUE){
  _fputts( _T("Unable to create mailslot ! \n"), stdout);
  return 1;
 }

 while(1){
  _fputts(_T("shell) "), stdout);
  _fgetts(message,sizeof(message)/sizeof(TCHAR), stdin);

  if(!WriteFile(hMailSlot,message,          //우체통에 글을 써버림.
   _tcslen(message)*sizeof(TCHAR), &bytesWritten, NULL)){
    _fputts( _T("Unable to write ! "), stdout);
    CloseHandle(hMailSlot);
    return 1;
  }

  if(!_tcscmp(message, _T("EXIT"))){    //입력문자열이 EXIT 면 끝!
   _fputts(_T("Good Bye!"), stdout);
   break;
  }
 }
 CloseHandle(hMailSlot);
 return 0;
}


 

반응형

+ Recent posts