봉황대 in CS

[Chapter 6. 프로세스 동기화] 세마포어 본문

Computer Science & Engineering/Operating System

[Chapter 6. 프로세스 동기화] 세마포어

등 긁는 봉황대 2022. 7. 25. 21:42

* 본 글은 '운영체제(Operating System: Concepts) 9th edition'의 내용과 2021학년도 1학기에 수강한 '운영체제' 과목 강의 내용을 함께 정리하여 작성하였습니다.

 

 

공유 변수의 간섭 문제를 해결하기 위한 상호 배제 및 동기화 프로그래밍 수단으로는

뮤텍스(Mutual Exclusion, Mutex)와 세마포어(Semaphore)가 있다.

 

 

Mutex는 while문을 사용하는 busy waiting 알고리즘이었다면,

세마포어는 프로세스를 자원 가용 상태에 따라 대기 상태 또는 준비 상태로 천이시키는 block/wakeup 알고리즘이다.

 

세마포어 (Semaphore)


세마포어는 일종의 객체로, 다음의 구성을 가진다.

 

  • 하나의 정수 변수 (value)
  • 프로세스 대기 큐
  • 정수 변수에 대한 3가지 연산
typedef struct {
    int value;
    struct process *list;
} semaphore;

 

value는 가용한 자원의 개수로 초기화하며, 자원의 활용 현황을 나타내게 된다.

* 양수일 경우 : 남아있는 자원의 수

* 음수일 경우 : 자원을 대기하고 있는 프로세스의 수

 

 

세마포어에 대한 연산에는 다음의 3가지가 존재한다.

 

  1. init : 초기화
  2. wait() - P 연산
  3. signal() - V 연산

* 네덜란드어로 '검사하다'를 의미하는 Proberen, '증가하다'를 의미하는 Verhogen의 앞 글자를 땀

 

 

1. value를 가용한 자원의 개수로 초기화한다.

// 초기화
init(semaphore *S, int n) {
    S->value = n; // 자원이 n개
}

 

2. 각 자원을 사용하려는 프로세스는 세마포어에 wait() 연산을 수행한다.

wait() 연산을 통해 세마포어의 값은 감소한다.

// P 연산
wait(semaphore *S) {
    S->value--; // 자원 하나를 할당할 예정
    
    if (S->value < 0) { // 음수일 경우 == 자원이 부족할 경우
        해당 프로세스를 S->list(대기 큐)에 넣음;
        block(); // 대기 상태로 천이
    }
}

만약 세마포어의 값이 0이 되었다는 것은 모든 자원들이 사용 중이라는 것이다.

이후에 자원을 사용하려는 프로세스들은 block() 연산에 의해 세마포어의 값이 0보다 커질 때까지 봉쇄된다.

 

봉쇄된다는 것은 프로세스가 세마포어에 연관된 대기 큐에 들어가고, 프로세스의 상태가 대기 상태로 천이된다는 것이다.

 

 

3. 프로세스가 자원을 방출할 때는 signal() 연산을 수행한다.

signal() 연산을 통해 세마포어의 값은 증가한다.

// V 연산
signal(semaphore *S) {
    S->value++; // 자원 하나를 반납할 예정
    
    if (S->value <= 0) { // 적어도 하나의 스레드는 자원을 할당받기 위해 대기하고 있었다는 것
        S->list(대기 큐)로부터 하나의 프로세스 P를 꺼냄;
        wakeup(P); // 준비 상태로 천이
    }
}

세마포어를 대기하면서 봉쇄되었던 프로세스는 다른 프로세스가 signal() 연산을 실행하면 재시작되어야 한다.

wakeup(P) 연산에 의해서 대기 큐에 있었던 프로세스는 준비 상태로 천이되어 준비 큐에 들어가 스케줄링될 수 있게 된다.

 

 

 

wait() 그리고 signal() 함수는 원자적(atomic)으로 실행되어야 한다.

 

하지만 이 두 함수를 실행하는 데 걸리는 시간은 매우 짧기 때문에, 이를 위한 임계 구역을 만들어야 한다.

따라서 value를 대상으로 compare_or_lock() 또는 spinlock 기법을 사용하기도 한다. (busy waiting 기법들)

 


세마포어의 value는 가용한 자원의 개수로 초기화된다.

해당 초기값(n)을 어떻게 설정하느냐에 따라 세마포어는 다양한 목적으로 활용할 수 있다.

 

1. n > 1

자원이 여러 개 있을 경우, 자원과 대기자를 동시에 관리할 수 있다.

(1) 현재 value의 값이 양수일 경우 : 남아있는 자원의 수

(2) 현재 value의 값이 음수일 경우 : 자원을 대기하고 있는 프로세스의 수

 

2. n == 1

공유 변수에 대한 mutex lock과 유사하게 동작한다.

 

 

3. n == 0

사건(event)에 의한 다중 스레드 간의 순서화(serialization)에 사용된다.

즉, 두 스레드 간의 수행 순서를 조절하는 용도로 사용되는 것이다.

 

 

 

반응형
Comments