2012년 8월 29일 수요일

윈도우즈 시스템 프로그래밍 [7] - 프로세스간 통신 (IPC)




윈도우즈 시스템 프로그래밍을 공부하면서 정리한 글입니다.



7장.  프로세스간 통신 (IPC) 1



I. 프로세스간 통신(IPC)의 의미



- IPC = Inter-Process Communication ( 프로세스 사이의 통신 )
- 통신 : 기본적으로 데이터를 주고 받는 행위
- 대부분 하나의 프로그램 = 하나의 프로세스 but  여러개의 프로세스를 가진 프로그램도 종종 있음



1. 프로세스 사이에서 통신이 이뤄지기 위한 조건


- 서로 통신하고자 하는 프로세스가 만날 수 있는 여건 (공유하는 메모리 영역이 존재)이 되어야 함
- 여건이 허락되지 않으면 전화 or 메신저 같은 보조 수단이 필요


2. 프로세스들이 서로 만날 수 없는 이유


- 프로세스는 서로 데이터를 주고 받을 만한 접선 장소가 없기 때문에 데이터 주고받는 것은 불가능
- 프로세스는 자신에게 할당된 메모리 공간 이외의 접근은 불가능


3. 프로세스들이 만나지 못하게 디자인한 이유 


- 안정성을 높이기 위해





II. 메일 슬롯 방식의 IPC




1. 메일 슬롯 (Mail Slot)의 원리


- 파이프와 더불어 대표적인 IPC 기법
- 메일 슬롯 : 편지를 넣을 가느다란 우체통의 입구
- 기본 원리 : 데이터를 주고받기 위해 프로세스가 우체통을 마련


2. 메일 슬롯 (Mail Slot) 구성을 위해 필요한 요소


 ① Receiver가 준비해야할 것

HANDLE CreateMailslot (
   LPCTSTR lpName,
   DWORD nMAXMessageSize,
   DWORD lReadTimeout,
   LPSECUritY_ATTRIBUTES lpSecurityAttributes
);

1) lpName : 생성하는 메일 슬롯의 이름
   - 주소의 기본 형식 : \\computer name\mailslot\[path] name

2) nMaxMessageSize : 메일 슬롯의 버퍼 크기를 지정
   - 0을 전달할 경우 시스템이 허용하는 최대 크기로 지정

3) lReadTimeout : 최대 블로킹 시간을 ms 단위로 전달
   - 메일 슬롯은 전소오딘 데이터를 읽기위해 파일 입/출력 함수 ReadFile 함수를 이용
   - 메일 슬롯이 비어 있다면 데이터가 채워질 때 까지 Blocking 상태에 놓임 
   - 0을 전달하면 데이터가 있든 없든 블로킹 상태를 빠져나와 다음 단계를 실행
   - MAILSLOT_WAIT_FOREVER을 인자로 전달하면 데이터가 존재할 때 까지 블로킹 상태에 놓임

4) lpSecurrityAttributes : 핸들의 상속 여부를 지정

5) 함수의 변환 타입 : HANDLE
   => 메일 슬롯은 커널에 의해 관리되는 리소스 이므로 커널 오브젝트가 생성되며, 그 핸들이 반환됨


② Sender가 준비해야 할 것

- 메일 슬롯 이름을 알아야 함 (&주소 ( 디렉토리))

ex)

   HANDLE hMailSlot;
   hMailSlot=CreateFile("\\\\.\\mailslot\\ ", ...);   // 파일을 생성하거나 개방할때 사용
   CHAR message[50];
   WriteFile(hMailSlot, message, ...);

- CreateFile, WriteFile : Windows에서 제공하는 파일 관련 시스템 함수 ( <-> ANSI 표준함수)
- CreateFile을 통해 메일 슬롯으로 보내기 위한 통로(리소스)를 형성
   => 데이터 전송을위한 Data Stream을 형성
- 메일 슬롯은 파일이 아니지만 파일 입/출력 함수를 사용
   -> Windows 파일 시스템을 기반으로 구현되어 있기 때문

- 주소 골격 : \\computername\mailslot\[path] name
- 주소에서 'mailslot' 부분은 바뀌지 않음
- computername에 '.'의 의미 : 로컬 컴퓨터






- Sender 프로세스는 우체통(메일 슬롯)의 주소를 알고 있어야 데이터 전송이 가능
- 메일 슬롯 = 메모리 공유 역할
- 데이터 전송이 양방향이 아닌 단방향(우체통)
- 여러개의 리시버가 같은 주소를 가질 수 있음
   => 센더가 그 주소로 전송하면 모든 메일 슬롯에 데이터 전송이 가능 (브로드 케스팅)





- CreateFile : 파일 만들거나 오픈
- WriteFile : 파일에 데이터 작성

- IPC 메일 슬롯을 이용하지 않고 파일만으로 데이터를 주고받을 수 있음
   ex)
       프로세스 A가 파일 a.txt를 만들고 프로세스 B가 a.txt를 읽음
        => BUT 안정성에 문제가 있음 ->  메일 슬롯을 이용

ex) Receiver.cpp

#define SLOT_NAME _T("\\\\.\\mailslot\\mailbox");

int _tmain(int argc, LPTSTR argv[]) {
   HANDLE hMailSlot;
   TCHAR messageBox[50];
   DWORD bytesRead;

   hMailSlot = CreateMailSlot (
      SLOT_NAME,
      0,
      MAILSLOT_WAIT_FOREVER,
      NULL
   );

   ReadFile(hMailSlot, messageBox, sizeof(TCHAR)*50, &bytesRead, NULL);

   closeHandle(hMailSlot);   // UC 1줄여 커널 오브젝트의 소멸을 도움

ex) Sender.cpp

#define SLOT_NAME _T("\\\\.\\mailslot\\mailbox");

int _tmain(int argc, LPTSRT argv[]) {
   HANDLE hMailSlot;
   TCHAR message[50];
   DWORD bytesWritten;

   hMailSlot=CreateFile (  //  Receiver과 연결을 만들기 위해
      SLOT_NAME,
      GENERIC_WRITE,  // 여기서부터
      FILE_SHARE_READ,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL   // 여기까지 거의 고정
   );

   _fgetts(message, sizeof(messsage)/sizeof(TCHAR), stdin);
   WriteFile(hMail, message, _tcslen(message)*sizeof(TCHAR), &bytesWritten, NULL);

   CloseHandle(hMailSlot);

- 메일 슬롯 주소에서 '.'는 컴퓨터 자신, '*'는 모든 컴퓨터
  => 브로드 케스팅 이용 가능




III. Signaled vs Non-Signaled => 커널 오브젝트의 상태




1. 상태에 대한 이해


- 상태(state)라는 용어를 사용하는 이유는 변하기 때문
- signaled (신호를 받는 상태)와 Non-Signaled (신호를 받지 않는 상태)
- 커널 오브젝트를 구성하는 멤버 변수 중 하나가 상태 정보를 저장함
   => TRUE : Signaled   FALSE : Non-Signaled


2. 프로세스 커널 오브젝트 상태 (state)에 대한 이해


- 프로세스가 생성될 때 프로세스 커널 오브젝트가 생성됨
   => 처음 상태 : Non-signaled
- 프로세스가 종료되면 Signaled 상태로 변경됨
- Signaled 된 커널 오브젝트는 Non-Signaled 상태로 변경되지 않음
   => 종료된 프로세스를 다시 재개하지 못하기 때문 ( 새로운 프로세스를 다시 실행해야 함)


3. 커널 오브젝트의 두가지 상태를 확인하는 용도의 함수


- 커널 오브젝트의 상태를 확인하는 대표적인 함수

ex) DWORD WaitForSingleObject (
         HANDLE hHandle,   // 확인하려는 커널 오브젝트의 핸들
         DWORD dwMilliseconds   // 커널 오브젝트가 Signaled 될 때 까지 기다릴 수 있는 최대 시간
       );

- dwMilliseconds에 IFINITE 인자 전달시 Signaled 될 때까지 기다림

- WaitForSingleObject 반환값
   1) WAIT_OBJECT_0 : 커널 오브젝트가 Signaled 되었을 때 반환값
   2) WAIT_TIMEOUT : Signaled 되지 않고 dwMillisecons가 다 되었을 때
   3) WAIT_ABANDONED : 오류 발생시



4.  커널 오브젝트의 상태 확인이 필요한 상황

      => 하나의 프로그램이 여러개의 프로세스로 구성되는 경우 (CPU 코어 수의 증가에 따라)


- 이런 상황에서 WaitForSingleObject 사용







참고 : 뇌를 자극하는 윈도우즈 시스템 프로그래밍. 윤성우 저 





댓글 없음:

댓글 쓰기