Semaphore
세마포어는 추상 자료형이다.
여기서 추상 자료형이란 "기능의 구현 부분을 나타내지 않고 순수한 기능이 무엇인지 나열한 것을 추상 자료형" 이라고 한다.
전자레인지 시작버튼을 누르면 전자레인지에서 sw/hw 적으로 어떻게 동작하는지는 모르지만 전자레인지가 동작하게 된다. 이렇게 추상 자료형은 내부적으로 어떻게 구현되었기 보다는 기능과 사용방법을 정의한 것을 말한다.
이런 관점에서 세마포어를 이해해 보자면, 세마포어는 여러 프로세스가 하나의 공유자원에 접근하는 것을 제어하는 역할을 한다. semaphore는 정수값을 가지며 이 정수값에 P(S)와 V(S), 2가지 연산을 할 수 있다.
1. P(S) : semaphore를 획득(= 공유자원에 대한 접근권한을 얻음)
P(S)연산은 공유자원에 대한 접근권한을 얻는 연산으로, semaphore값이 5라면 P(S)연산을 하면 semaphore값은 4가 된다.
이는 공유자원에 대한 접근권한을 얻었음을 의미한다.
만약 P(S) 연산을 하기 전에 semaphore <= 0인 경우라면 획득할 수 있는 semaphore가 없기 때문에 다른 프로세스가 semaphore를 반납하기 전까지 기다린다.
이때 기다리면서 while()에서 대기를 하면서 CPU를 계속 사용한다. (busy waiting = spin lock)
2. V(S) : semaphore를 반납(= 공유자원을 사용하고 접근권한을 반납)
V(S)연산은 공유자원에 대해 접근하여 연산을 하다 다 사용하고 접근권한을 반납하는 연산이다.
이 때 권한을 반납하면서 V(S)연산을 수행하면서 semaphore값은 하나 증가 시킨다.
semaphore는 2가지의 타입이 있습니다.
- counting semaphore
도메인이 0 이상인 임의의 정수 값으로 주로 자원에 접근할 수 있는 프로세스의 수를 제어하는데 사용한다. - binary semaphore (= mutax)
0 또는 1 값만 가질 수 있는 세마포어로 주로 mutual exclusion(lock / unlock)에 사용한다.
Block / WakeUp으로 구현
세마포어의 P(S)연산의 경우, 만약 공유자원에 대한 접근을 얻지 못하면 해당 프로세스는 while()에서 세마포어를 얻을 때까지 계속 유한대기를 하기 때문에 CPU를 낭비하게 된다.
해당 프로세스가 CPU를 받아도 그냥 while()에서 대기한다. 그리고 이런 현상을 busy waiting(spin lock)이라고 한다.
이런 방법말고 해당 프로세스를 blocked시키고 다른 프로세스가 세마포어를 내놓을 때 그 때 다시 깨워주는 방법(CPU Ready Queue에 삽입)이 더 효율적이다.
block/wakeup방식으로 semaphore를 구현할 때 P()연산과 V()연산은 다음과 같습니다.
1. P(S)
P(S)연산의 경우 semaphore를 하나 가져가기 때문에 S.value를 하나 뺀다.
만약 음수인 경우 해당 프로세스를 semaphore를 기다리는 wait queue에 넣고 block()시킨다. 이렇게 되면 해당 프로세스가 CPU를 받을 일이 없게 되어 busy waiting이 해결된다.
2. V(S)
자원을 반납할 때는 S.value를 하나 증가 시킨다. 근데 만약 하나 증가시켰는데도 그 값이 0 이하라는 것은 내가 semaphore를 내놓기를 기다리고 있는 프로세스가 있다는 의미입니다(block되어 있음).
그렇기 때문에 wait queue에 잠들어 있는 프로세스를 깨워준다.
Busy - wait vs Block/wakeup
Busy - waiting 는 semaphore를 기다리는 프로세스가 CPU를 받았을 때 CPU를 사용하는 시간 동안 계속 대기(while(1))하는 경우를 말한다.
Block/wakeup는 sempahore를 기다리는 프로세스를 CPU를 받지 못하게 아예 block시키는 방법이다.
나중에 다른 프로세스가 semaphore를 내놓으면 block되어 있는 프로세스를 깨우는 방법으로, 이 방법은 프로세스를 block/wakeup하는데 오버헤드가 발생한다.
보통은 block/wakeup을 사용하는 경우가 효율적이다.
굳이 cpu를 줘도 못쓰는 프로세스에게 cpu를 줄 필요는 없다. 하지만 오버헤드가 존재하기 때문에 임계영역의 매우 짧은 경우는 busy - waiting해도 무방하지만 임계영역의 긴 경우는 아예 block해버리는 경우가 더 낫다.
'OS' 카테고리의 다른 글
[운영체제] Deadlock(교착상태) (0) | 2022.09.12 |
---|---|
[운영체제] 프로세스 동기화 3 (1) | 2022.09.12 |
[운영체제] 프로세스 동기화 1 (0) | 2022.09.11 |
[운영체제] 시스템 구조 및 프로그램 실행 (1) | 2022.09.11 |
[운영체제] 인터럽트 (0) | 2022.09.11 |