블링블링 범블링

[OS 8장]프로세스 관리 - 세마포(semaphore) 본문

Technology/오퍼레이팅 시스템

[OS 8장]프로세스 관리 - 세마포(semaphore)

뻠스키 2018. 4. 17. 17:34


프로세스/쓰레드 동기화는 여러 개의 프로세스/쓰레드가 공통으로 데이터에 접근하려고 할 때 발생하는 문제를 해결하는 방법이다동기화 부분은 스케줄링과 더불어 프로세스 관리에서 매우 중요한 부분을 차지한다세마포는 프로세스/쓰레드 동기화를 위한 도구 중 하나이다앞장에서 세마포의 원리에 대해서 알아보았는데 이번 장에서는 더욱 자세히 세마포에 대해 다루어보도록 하겠다.


쓰레드가 동작하는 공간에는 공통 데이터를 수정할 수 있는 임계구역이 존재한다쓰레드가 동작을 하면서 임계구역에 들어가게 되면 데이터를 수정할 수 있다쓰레드가 코드를 동작하는 도중에 acquire() 명령어가 실행되면 임계구역에 들어가라는 명령이므로 쓰레드가 임계구역에 들어간다임계구역에 있는 쓰레드는 release()라는 명령어가 실행되면 임계구역에서 나오게 된다이러한 명령어들은 쓰레드 안에 작성된 값이다.


여기서 문제가 발생할 수 있는 것은 하나의 쓰레드가 자신의 임계구역에 들어가서 공통으로 사용하는 데이터를 수정하고 있는 상황에서 문맥 전환(context switching)에 의해 다른 쓰레드가 자신의 임계구역에 가서 공통으로 사용하는 데이터를 수정하려고 시도할 때이다이렇게 되면 결과적으로 데이터의 수정이 이상하게 변동될 수가 있다이러한 문제를 임계구역 문제라고 한다.


위와 같은 문제가 발생하지 않게 하는 방법이 바로 상호배타(Multual exclusion)이다그러면 어떻게 상호배타를 만족시킬 수 있게 할 수 있는가이 때 사용하는 도구가 바로 세마포이다세마포는 정수 값을 가지는데 처음에 나타나는 정수는 임계구역에 들어갈 수 있는 쓰레드의 수를 나타낸다한 쓰레드가 acquire() 명령어를 실행해서 임계구역에 들어가게 되었을 때 문맥 전환에 의해 다른 쓰레드가 acquire() 명령어를 실행했다고 하더라도 임계구역에 들어갈 수 없게 막는 공간이 바로 세마포이다.



세마포이 동기화에서 적용되는 동작원리를 상세히 살펴보자. 

세마포는 쓰레드를 보관하는 Queue를 가진다그리고 앞에서 말했듯 정수 값을 가진다여기서는 시작하는 정수 값을 1로 놓고 설명을 하겠다임계구역에 접근 가능한 쓰레드가 하나라는 것을 의미한다임의의 쓰레드가 임계구역에 쓰레드가 존재하지 않을 경우 acquire()명령을 실행할 수 있다세마포는 acquire()명령을 받을 경우 정수 값을 1감소시킨다그리고 정수 값이 0보다 작을 경우 세마포의 Queue에 쓰레드를 block시킨다하지만 지금의 정수 값이 1이였는데 쓰레드가 acquire()명령을 실행한 경우 0이 되므로 세마포의 Queue에 갇히지 않고 바로 임계구역으로 이동하여 명령을 수행한다하지만 컴퓨터의 CPU 할당은 문맥 전환(context switching)에 의해 다른 쓰레드에게 갈수 있다따라서 다른 쓰레드가 문맥 전환에 의해 코드가 실행되게 되었다고 가정하자그런데 이 다른 쓰레드가 또 acquire()명령을 실행을 하게 되면 어떻게 될까두 번째 쓰레드도 임계구역에 들어가고 싶어 한다하지만 임계구역에는 이미 하나의 쓰레드가 존재하고 있으므로 임계구역에 들어가면 안 된다이를 제어하는 것이 바로 세마포이다. acquire()명령이 또 실행되었으므로 세마포의 정수 값이 또 1감소하게 된다그러면 정수 값은 1이 되어 0보다 작은 값을 가지게 된다이렇게 되면 두 번째 쓰레드는 세마포의 Queue에 block을 당해 임계구역에 접근을 하지 못하는 상황이 된다세마포의 Queue에 block을 당한 쓰레드는 혼자 힘으로 풀려나갈 수 없다그렇다면 어떻게 두 번째 쓰레드는 임계구역에 들어갈 수 있는가세마포에서 줄을 서서 잘 기다리고 있으면 다시 문맥 전환에 의해 앞에 먼저 임계구역에 들어간 쓰레드가 release()라는 명령을 수행할 수 있게 되고 이를 통해 임계구역에서 나가고 싶다는 의사를 표시한다그렇게 되면 세마포는 이를 인지하여 정수 값을 1증가시킨다그렇게 되면 정수 값이 0보다 크게 되므로 줄을 서고 있는 쓰레드가 wakeup을 통해 세마포에서 탈출을 하게 된다이렇게 탈출한 쓰레드는 임계구역에 접근을 허가받게 되어 들어가서 데이터를 수정할 수 있게 된다이런 방식으로 동시에 임계구역을 접근할 수 없게 하는 상호배타가 적용이 가능하게 된다.






세마포는 프로세스 실행 순서를 원하는 대로 제어하는 역할로도 사용할 수 있다

이를 Ordering이라고 한다예를 들어 설명해보자프로세스가 P1과 P2가 있다고 하자각각의 프로세스는 각자의 코드를 가지고 있다. P1은 S1이라는 내부 코드를 P2는 S2라는 내부 코드를 가지고 있다고 가장하자그런데 여기서 우리는 CPU 스케줄링과 상관없이 무조건 P1의 S1이 먼저 실행시키고 싶다고 하자그러면 어떻게 코드를 짜야할까우리는 세마포를 도구 사용하면 가능하다세마포는 정수 값과 프로세스 보관을 가지는 도구이다먼저 세마포의 정수 값에 0으로 놓는다초기 값은 허용되는 프로세스의 수이므로 0이면 아무도 허용이 되지 않는다는 것을 의미한다만약 P1이 먼저 실행되면 S1이 먼저 실행이 되므로 우리는 아무런 효과를 주지 않아도 된다하지만 만약 P2가 CPU 스케줄링에 의해 먼저 실행되게 된다면 우리가 의도한 대로 실행이 되지 않는 것이다그래서 우리는 임의로 P2의 실행코드 앞에 acquire()명령을 넣어준다. acquire()명령을 실행하면 세마포의 정수 값이 1감소하게 되어 1이 된다그렇게 되면 세마포의 정수 값이 0보다 작은 값을 가지게 되므로 P2는 세마포의 프로세스 보관 Queue에 block 당하게 된다그러면 뒤의 코드를 실행할 수 없는 상황에 생긴다그렇게 되면 어떻게 되든 문맥전환에 의해 P1이 먼저 실행하게 된다그런데 P2를 영원히 갇혀있게 하면 안 된다따라서 P1의 내부코드 끝부분에 release()명령을 넣는다그렇게 되면 세마포의 정수 값이 1증가하게 되어 다시 0이 된다그러면 세마포에 저장된 P2가 wakeup이 되어 세마포에서 빠져나오게 된다이렇게 세마포를 이용한 명령을 임의로 입력해 넣어 우리가 원하는 프로세스의 처리 순서를 제어할 수 있다.


Comments