별다른 설정을 하지 않았다면 생성한 프로그램은 기본적으로 중복 실행이 가능하다.
중복 실행을 방지하기 위해선 CXXApp 클래스의 InitInstance() 함수에 다음과 같이 작성한다.

 

BOOL ChRmtEvwrApp::InitInstance()
{
    HANDLE hEvent = NULL;


    hEvent = ::CreateEvent(NULL, FALSE, TRUE, ::AfxGetAppName());
    if (NULL == hEvent)
       return FALSE;
 
    if (ERROR_ALREADY_EXISTS == ::GetLastError())
       return FALSE;
    
     ...
  

   return TRUE;
}


::CreateEvent() 함수는 스레드간의 작업 순서나 시기를 조정해 주는 동기화 객체이다.
정확히 말해선 Kernel Object 이다.

함수의 첫번째 인자로는 보안특성을 설정해 준다. NULL을 주면 해당 Event Kernel Object의
핸들을 자식 프로세스에게 상속하지 않는다는 것이다. 여기선 이벤트 핸들을 가지고 특별한
작업을 하는 것은 아니므로 NULL을 준다.

두번재 인자로는 이벤트 종류를 설정하는데 FALSE값을 주어 수동 리셋 이벤트 객체를
만들어 주었다. (여기선 그리 중요한 설정 사항이 아니다.)

 세번째 인자로는 이벤트 객체의 처음 상태를 설정 하는데 TRUE로 줌으로써 신호상태 이벤트
를 만들어 주었다. 

 네번째 인자가 중요하다. 네번째 인자로는 이벤트 객체의 이름을 지정해 준다. 이 이름은
나중에 이벤트 객체를 열 때 사용한다. 

 이렇게 처음 프로그램을 실행 시키면 ::CreateEvent() 함수는 이벤트 객체를 리턴하며 아래
문장을 실행하고 TRUE를 리턴한다.

 프로그램을 실행 시킨 상태에서 또 이 프로그램을 실행 시키면 ::CreateEvent() 함수는
네번째 인수로 이벤트 객체를 만들려고 시도한다. 하지만 네번째 인자로 주어지는 이름이
처음 프로그램을 실행시켰을 때 이벤트 객체를 만든 이름과 동일한 이름으로 이벤트 객체를
만들려고 하므로 ::CreateEvent() 함수는 처음 프로그램이 만든 이벤트 객체를 리턴한다.

이 때 ::GetLastError() 함수를 호출하면 ERROR_ALREADY_EXISTS 를 리턴한다.
이 값일 때 프로그램을 바로 종료하게 만들면 프로그램의 중복 실행을 막을 수 있다.
어떻게 보면 프로세스간 동기화 기법인 이벤트를 이용한 것이지만 이벤트 객체가
Kernel Object 라는 것을 아는게 더 선수 지식 같다.

Kernel Object 는 프로세스간 공유될 수 있지만 각 프로세스에서 동일한 핸들 값을 갖지는
않는다. (프로세스 한정적)

Posted by six605
,