앞에서는 동기화의 필요성과 유저모드에서 사용 가능한 동기화 기법에 대해서 말했다.
유저모드의 특징은 다음과 같겠다.
. 커널 모드에 비해 속도가 월등히 빠르다
. 하나의 프로세스의 내부에 존재하는 스레드들에 대한 동기화만 가능하다.
. 임계영역을 사용시 Timeout 값을 명시할 수 없어 커널 모드에 비해 데드락에 빠지기 쉽다.
위 특징에서 보면 알수있지만 단점이 많지만 속도에 갈망하는 우리 프로그래머들인지라. 유저모드를 많이 사용할 수 밖에 없다.
커널모드의 동기화는 커널 오브젝트의 상태변화(시그널, 넌시그널) 를 체크함으로서 이루어지는 동기화 기법이다. 스레드가 대기중인 커널 오브젝트의 상태가 넌시그널 상태이면 해당 스레드는 대기모드로 전환이 되어 해당 커널 오브젝트가 시그널 상태가 될때까지 대기를 하며 해당 오브젝트가 시그널 상태로 변경이되면 해당 스레드는 대기모드에서 스케쥴 가능상태가 되어 실행을 한다.
시그널 또는 넌시그널 상태가 될 수 있는 커널 오브젝트는 다음과 같다.
. 프로세스
. 스레드
. 작업(Job)
. 파일
. 콘솔입력
. 파일 변경 알림
. 이벤트
. 대기 타이머(Waitable Timer)
. 세마포어
. 뮤텍스
◎ 대기 함수(Wait Functions)
대기 함수는 특정 오브젝트가 시그널 상태가 될때까지 스레드가 스스로 대기 상태에 들어가도록 하는 함수이다. 대기 함수에는 아래와 같은 함수들이 존재한다.
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);
DWORD WaitForMultipleObejcts(DWORD dwCount, const HANDLE* phObjects,
BOOL fWaitAll , DWORD dwMillionseconds);
WaitForSingleObject는 하나의 커널 오브젝트에 대해 대기를 하는 함수이다. HANDLE은 대기하고자하는 커널 오브젝트의 핸들이며 dwMilliseconds는 대기 하고자하는 시간이다(밀리세컨드) 더 자세한 부분은 MSDN을 참조하길 바란다.
WaitForMultipleObejcts은 다수의 커널 오브젝트에 대해 대기를 하는 함수이다.
dwCount는 대기 하고자하는 오브젝트의 개수 이며, phObjects는 오브젝트핸들 배열의 주소이다. fWaitAll이 TRUE이면 배열의 모든 오브젝트가 시그널상태가 되야만 해당 스레드가 활동을 한다. 만약 반대이면 하나의 오브젝트라도 시그널 상태가 되면 해당 스레드는 활동을 개시한다. 더 자세한 부분은 MSDN을 참조하길 바란다.
◎ 이벤트 커널 오브젝트
커널 오브젝트에서 가장 원시적인 단위며, 이벤트 커널 오브젝트는 사용번호, 오토리셋 Or 매뉴얼 리셋인지를 나타내는 Boolean값, 시그널인지 넌시그널 상태인질ㄹ 나타내는 Boolean값으로 이루어져있다.
. 오토 리셋 : 이벤트가 시그널이 되면 해당 이벤트를 기다리는 스레드 중 하나의 스레드만
스케쥴 가능하게 변경이되며, 이벤트는 다시 넌 시그널로 세팅된다.
. 매뉴얼 리셋 : 이벤트가 시그널이 되면 해당 이벤트를 기다리는 모든 스레드는 스케쥴 가능하게 변경이되며, 해당 이벤트는 수동으로 넌시그널로 변경을 해야한다.
. 관련 API
| CreateEvent | 이벤트 객체를 생성한다. (보안속성, 매뉴얼 리셋 여부, 최초 상태, 이벤트 객체 이름부여를 할 수 있다.) |
| OpenEvent | CreateEvent 시 이벤트 명을 명시한 객체에 한해서 OpenEvent 로 접근을 할 수 있다. |
| SetEvent | 이벤트를 시그널 상태로 변경한다. |
| ResetEvent | 이벤트를 넌시그널 상태로 변경한다. |
| PulseEvent | 이벤트를 시그널과 넌시그널이 되게 한다. 이는 ResetEvent 후에 SetEvent 를 호출하는것과 같다. 매뉴얼 리셋 이벤트에 PulseEvent를 호출하면 이벤트를 기다리던 모든 스레드는 스케쥴 가능하게 된다. 오토리셋 이벤트에 사용하면 대기중인 스레드중 하나만 스케쥴가능하게 된다. |
후에 맘 변하면 추가 하겠음
