728x90

커널모드에서 동작하는 동기화 기법을 커널모드 동기화 기법이라고 한다.

커널모드 동기화는 유저모드 동기화에 비하면 느리다. 유저모드에서 커널모드로, 커널모드에서 유저모드로의 전환이 필요하기 때문이다. 그러나 커널모드 동기화 기법에서는 유저모드 동기화가 제공해주지 못하는 기능을 제공받을 수 있다.

 

뮤텍스(Mutex)기반의 동기화

뮤텍스 기반 동기화 기법의 경우 크리티컬 섹션 오브젝트와 같이 뮤텍스 오브젝트가 존재한다. 이는 크리티컬 섹션 오브젝트와 달리 다음 함수를 통해서 만들어 진다.

HANDLE CreateMutex(

    LPSECURITY_ATTRIBUTES lpMutexAttributes,

    BOOL bInitialOwner,

    LPCTSTR  lpName

);

1.lpMutexAttributes : 뮤텍스도 커널오브젝트 이기 때문에 이 값을 통해 보안속성을 지정해 줄 수 있다.

2.bInitialOwner : 뮤텍스는 뮤텍스 오브젝트를 생성하는 쓰레드에게 임계영역에 접근하는 기회를 먼저 줄 수 있다. FALSE를 전달할 경우 크리티컬 섹션처럼 먼저 접근하는 쓰레드가 임자가 되게할 수 있다. TRUE를 전달할 경우 뮤텍스를 생성하는 쓰레드가 먼저 기회를 얻을 수도 있다. 이를 결정하는 전달인자이다.

3.lpName : 뮤텍스에 이름을 붙여주기 위해 사용한다. 이름은 널(NULL)문자로 끝나는 문자열로 저장하면 된다. 이름을 주었을 때 생성되는 뮤텍스를 가리켜 Named Mutex(이름있는 뮤텍스)라 표현한다.

4.함수의 반환타입 HANDLE : 반환 타입이 HANDLE이라는 것은 뮤텍스가 커널 오브젝트임을 말하는 것이다.

 

뮤텍스가 커널 오브젝트인 점만 보더라도, 뮤텍스는 커널레벨 동기화 기법임을 알 수 있다. 뮤텍스는 함수 호출 과정에서 필요한 모든 초기화가 이루어 진다.

 

 "커널 오브젝트는 상태를 지닌다. 하나는 Signaled 상태이고, 다른 하나는 Non-Signaled 상태이다."

보통 커널오브젝트는 Non-Signaled 상태에 놓여있다가, 특정 상황이되면 Signaled 상태가 된다.

 

뮤텍스는 누군가에 의해 획득이 가능할 때 Signaled 상태에 놓이고 누군가에 의해 획득되어져 있는 상태라면 Non-Signaled 상태가 된다.

 

뮤텍스는 획득이 가능할 때 Signaled 상태에 놓인다. 따라서 WaitForSingledObject 함수를 임계영역 진입을 위한 뮤텍스 획득의 용도로 사용가능하다.

 

뮤텍스를 반환할 때 사용하는 함수(뮤텍스를 Signaled 상태로 설정)

BOOL ReleaseMutex(

   HANDLE hMutex

);

1.hMutex : 반환할 뮤텍스 핸들을 인자로 전달한다. Non-Signaled 상태에 있는 뮤텍스 오브젝트는 Signaled 상태가 된다.

 

WaitForSingleObject 함수의 특성 : WaitForSingleObject 함수는 인자로 전달된 핸들의 커널오브젝트가 Signaled상태가 되어서 반환하는 경우, 해당 커널 오브젝트를 Non-Signaled 상태로 변경해 버린다.

 

뮤텍스 동기화는 ReleaseMutex 함수와 WaitForSingleObject 함수로 조절 가능하다.

 

쓰레드는 임계영역에 들어가기에 앞서 뮤텍스를 획득해야한다. 따라서 뮤텍스 핸들을 인자로 전달하면서 WaitForSingleObject함수를 호출한다. 뮤텍스가 획득가능한 상태라면 Signaled 상태일 것이다. 때문에 뮤텍스를 획득하면서 임계영역에 진입하게 된다. WaitForSingleObject함수는 커널오브젝트가 Signaled 상태가 되어 반환할 경우, 해당 커널오브젝트 상태를 Non-Signaled 상태로 변경하므로, 다른 쓰레드들은 임계영역으로의 진입이 제한된다. 임계영역에서의 일을 마친 쓰레드가 임계영역을 빠져 나오면서 ReleaseMutex함수를 호출한다. 이 함수가 호출되면, 뮤텍스는 다른 누군가에게 획득이 가능한 상태, 즉 Signaled 상태가 되어서 다른 쓰레드의 진입을 허용한다.

 

뮤텍스는 커널 오브젝트이다. 해당 리소스를 제거할 때는 CloseHandle 함수를 통해 반환하면 된다. 소멸은 운영체제가 해준다.

728x90

+ Recent posts