삽질의 현장/- 윈도우 시스템

#022_WIndow_System_유저모드 동기화 객체

shovelman 2015. 9. 24. 16:28


안녕하세요 삽잡이입니다.


지난시간까지 동기화에 대해서 정의를 해봤습니다.

그렇다면 이제는 동기화 기법에 대해서 살펴볼 시간이 찾아왔다는 것입니다...


동기화에는 '유저 모드 영역'과 '커널 모드 영역' 이 두 가지 종류의 동기화 객체들이 있습니다.

우선, 유저 모드 동기화 기법을 살펴보도록 하겠습니다.


첫번째로, Critical Section을 살펴보도록 하겠습니다.

Critical Section은 임계영역이라고 부릅니다. 그리고 이 임계영역은 필요한 곳에 설치를 해야합니다.

즉, 어떤 작업이 완료될 때 까지 다른 놈들이 오는 것을 막는 문을 설치하는 것입니다.


문을 설치했다면, 그 문을 열쇠만 있을 경우 열 수 있도록, 키를 생성해야합니다.

CRITICAL_SECTION 구조체를 통해서 말입니다.


그리고, InitializeCriticalSection 함수를 통해 문을 만들고, 
DeleteCriticalSection 만든 문을 부셔버리면 됩니다. (ㅎㅎㅎ...)
그러면 문을 만들고 부시기 이전까지는 열쇠를 통해 들락날락 거릴 수 있도록 해야하는데
이는 EnterCriticalSection 함수와 LeaveCriticalSecion 함수를 사용하면 됩니다.

예시를 살펴보도록 하겠습니다.


굳이 코드를 해석할 필요가 없이,

임계 영역의 시작과 끝을 어떻게 사용하는 지에 대해서만 이해를 보여드린 것입니다.


위의 부분... 

즉, 시작과 끝 부분을 실행하는 데 있어서 단 하나의 쓰레드만이 동작하는 것이 핵심입니다.


여러 키를 생성하고, 임계영역을 여러개 만들게 되면, 

해당 임계 영역들은 매개변수로 받는 키값에 따라서 달라지게 됩니다.

임계영역이 다르다는 소리는 쓰레드가 동시에 들어갈 수 있게 되는 것을 알고 사용하여야됩니다.


지금 우리가 알아가는 것은,

비동기적인 작업을 동기화 하는 방법을 살펴보는 것입니다.

그 중에서도 자세하게는 데이터 보호 작업에 대해서 살펴 보는 것입니다.



다음으로, '원자적인 연산'에 대해서 알아보도록 하겠습니다.

원자는 atomic이라고도 부르는데요, 이 영어 단어는 핵, 원자의 뜻을 가지고 있습니다.


아무튼... 원자적인 연산이란,

쓰레드가 실행 될 때 (어떤 명령을 실행하는 데 있어서) 

다른 쓰레드에 의해서 영향받지 않고 실행할 수 있는 최소 실행 단위의 연산을 말합니다.


원자적인 연산을 한다는 것은...

명령이 실행 되는 동안에 Ready 상태로 내려오지 않는 것입니다.

즉, 명령을 실행하다가 또 다른 쓰레드가 Running 상태로 가서는 안됩니다.


일반적으로 어셈블리 명령 하나가 원자적인 연산이라고 합니다.


'++val;'

이라는 코드 한줄을 어셈블리 명령으로 나눈다면 어떻게 될까요...

우선, ++val 은 val = val+1; 로 나타낼 수 있습니다.


어셈블리 명령으로 사용한다면 어떻게 될까요...

val의 값을 읽어오는 Read 연산, 1을 더하는 Add 연산, 다시 val 값을 쓰는 Write 연산...

이와 같이 세개의 어셈블리 연산이 한 코드에 들어가있습니다...


따라서 '++val;' 이라는 코드는 원자적 연산이 아닙니다.

이 명령을 하는 동안, 

즉, Read를 하는동안, Add를 하는 동안 혹은 Write를 하는동안

다른 쓰레드가 개입할 수 있다는 것입니다.



쓰레드가 두 대가 있다고 가정해봅시다.

그리고 두 쓰레드는 int형 val 변수를 공유한다고 해보겠습니다...


두 쓰레드가 '++val;' 연산을 수행하는데 어셈 블리 연산을 수행하는 동안 쓰레드 개입이 계속해서 발생된다면,

레지스터 셋(RS)이 쓰레드가 바뀔 때마다 바뀌기 때문에

해야할 작업이 완료되지도 않았는데, 다른 쓰레드에 의해서 연산이 방해 받게 됩니다.

따라서, 원자적 연산이 이뤄질 수 없겠지요...


전역변수만 문제가 아닙니다. 공유가 가능한 데이터라면, 이런 문제는 동일하게 발생합니다.

이럴 때 인터락을 사용하는 것입니다.



이처럼 인터락 함수는 원자적 연산을 보장해줍니다.

즉, 위의 코드는 1감소하는 동안 다른 쓰레드에게 방해를 받지 않게 됩니다.


인터락 함수에는 여러개가 있지만, 가장 많이 사용하는 함수로는

위의 예시에 있는 두 함수가 있습니다.


값을 원자적으로 만들어주는 것이 핵심입니다.



지금까지 유저 모드 동기화 객체에 대해서 알아봤습니다.

이상 삽잡이였습니다!