Critical Section(임계 영역) - Mutex
이번부터는 유저 모드 동기화가 아니라 커널 모드 동기화이다.
커널 모드 동기화는 유저 모드 동기화 달리 커널 자원과 유저 자원을 사용할 수 있다. 하지만 커널 모드에서 유저 모드로 변경 될 때 딜레이가 발생함으로 유저 모드 동기화보다 느릴 수 있다.
Mutex는 먼저 뮤텍스를 생성해야한다. 그 다음 임계 영역에서 WaitForSingleObject로 시작해서 ReleaseMutex 로 끝난다.먼저 예시를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | HANDLE Mutex; unsigned int WINAPI ThreadProc1(LPVOID lpParam) { for (DWORD i = 1; i <= 1000; i++) { WaitForSingleObject(Mutex, INFINITE); Sleep(1); Count++; ReleaseMutex(Mutex); } return 0; } unsigned int WINAPI ThreadProc2(LPVOID lpParam) { for (DWORD i = 1; i <= 1000; i++) { WaitForSingleObject(Mutex,INFINITE); Sleep(1); Count++; ReleaseMutex(Mutex); } return 0; } int _tmain() { Mutex = CreateMutex(NULL, FALSE, NULL); //코드 생략 CloseHandle(Mutex); } | cs |
HANDLE WINAPI CreateMutex(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, _In_ BOOL bInitialOwner, _In_opt_ LPCTSTR lpName );
먼저 뮤텍스를 생성한다. 이 API의 첫번째 파라미터는 보안 속성이다. 이 속성에서 핸들을 상속 여부를 결정하는데 이 파라미터를 사용하였다. 두번째 파라미터는 임계 영역에 어떤 것이 먼저 접근하냐를 설정하는 파리미터이다. FALSE 를 사용했을 시에 먼저 선점하는 경우 시작하고, TRUE를 했을 경우 뮤텍스를 생성하는 쓰레드가 먼저 기회를 얻는다. 세번째 파라미터는 뮤텍스에 이름을 줄 수 있다. 그리고 반환형이 핸들임을 생각해보자. 핸들은 커널 오브젝트를 가리킨다. 그럼 뮤텍스는 커널 오브젝트라는 걸 알 수 있다.
커널 오브젝트는 2가지 상태가 있다고 글에서 언급한적이 있다. 뮤텍스는 그것을 이용하여 동기화를 한다.
먼저 signaled 상태로 변환하는 API는 ReleaseMutex 이다.
BOOL WINAPI ReleaseMutex( _In_ HANDLE hMutex );
non-signaled 상태로 변경해주는 API인 WaitForSingleObject 이다.
DWORD WINAPI WaitForSingleObject( _In_ HANDLE hHandle, _In_ DWORD dwMilliseconds );
먼저 뮤텍스가 생성이 되어 임계영역 시작 부분에서 WaitForSingleObject 를 만나 뮤텍스는 non-signaled 상태가 된다. 그러면 다른 쓰레드가 접근을 하지 못하다 작업을 끝낸 뒤 ReleaseMutex 로 뮤텍스 상태를 signaled 로 바꿔 다른 쓰레드가 접근할 수있도록 한다.
뮤텍스를 다 사용했으면 마지막으로 뮤텍스를 반환해야하는데, HANDLE을 반환하는 CloseHandle을 사용하면 된다. 이 사용법은 다들 많이 봤을 테니 패스...
이번에는 뮤텍스를 생성할 때 세번째 파라미터에 이름을 주었을 때 어떻게 되는지 살펴 보도록 하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include<stdio.h> #include<tchar.h> #include<Windows.h> #include<process.h> HANDLE hMutex; DWORD dwWaitResult; void NamedMutex() { dwWaitResult = WaitForSingleObject(hMutex, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0: _tprintf(_T("Thread Signaled\n")); break; case WAIT_TIMEOUT: _tprintf(_T("Time Out\n")); break; case WAIT_ABANDONED: return; } for (DWORD i = 0; i < 5; i++) { _tprintf(_T("Thread Runing!!\n")); Sleep(1000); } ReleaseMutex(hMutex); } int _tmain() { hMutex = CreateMutex(NULL, FALSE, _T("Named")); _tprintf(_T("CreateMutex!!\n")); if (hMutex == NULL) { _tprintf(_T("CreateMutex Func err : %d\n"), GetLastError()); return -1; } NamedMutex(); CloseHandle(hMutex); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include<stdio.h> #include<tchar.h> #include<Windows.h> #include<process.h> HANDLE hMutex; DWORD dwWaitResult; void NamedMutex() { dwWaitResult = WaitForSingleObject(hMutex, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0: _tprintf(_T("Thread Signaled\n")); break; case WAIT_TIMEOUT: _tprintf(_T("Time Out\n")); break; case WAIT_ABANDONED: return; } for (DWORD i = 0; i < 5; i++) { _tprintf(_T("Thread Runing!!\n")); Sleep(1000); } ReleaseMutex(hMutex); } int _tmain() { hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("Named")); _tprintf(_T("OpenMutex!!\n")); if (hMutex == NULL) { _tprintf(_T("CreateMutex Func err : %d\n"), GetLastError()); return -1; } NamedMutex(); CloseHandle(hMutex); return 0; } | cs |
HANDLE WINAPI OpenMutex( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ LPCTSTR lpName );
출처 : OpenMutex MSDN
OpenMutex 는 첫번째 파라미터는 이름 있는 뮤텍스로 접근 권한을 지정하는 것이다. 아래 사이트를 참고해서 원하는 권한만 설정해도 좋고 귀찮으면 역시 MUTEX_ALL_ACCESS 두번째 파리미터는 핸들 상속을 묻는 파라미터이다. 세번째 파라미터는 뮤텍스 이름을 설정해준다. 여기서는 Named 라는 이름 있는 뮤텍스를 열고 있다.
'My Study > System' 카테고리의 다른 글
Cirtical Section(임계 영역) - CreateEvent (0) | 2016.07.08 |
---|---|
Critical Section(임계 영역) - Semaphore (0) | 2016.07.06 |
Critical Section(임계 영역) - Interlocked (0) | 2016.07.05 |
Critical Section(임계 영역) - CRITICAL_SECTION (0) | 2016.07.04 |
Critical Section(임계 영역) 개념 (0) | 2016.07.04 |