동기화 해결의 세 가지 원칙
운영체제에서 임계 구역 문제를 해결하기 위한 세 가지 원칙은 다음과 같다.
- 상호 배제 (mutual exclusion): 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
- 진행 (progress): 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 진입이 가능하다.
- 유한 대기 (bounded waiting): 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 진입이 가능해야 한다.
동기화 기법
1. 뮤텍스 락 (Mutex Lock)
상호 배제를 위한 동기화 도구이다. 공유 자원이 하나만 있는 경우에 적용이 가능하다. 자물쇠(lock)의 기능을 코드로 구현한 게 뮤텍스 락이다.
뮤텍스 락은 다음과 같이 구성된다.
- 자물쇠 역할을 하는 전역 변수: `lock`
- 임계 구역을 잠그는 역할을 하는 함수: `acquire()`
- 임계 구역의 잠금을 해제하는 역할을 하는 함수: `release()`
acquire() {
while (lock == true) // 만약 임계 구역이 잠겨있다면
; // 임계구역이 잠겨져 있는지 반복적으로 확인
lock = true // 만약 임계 구역이 잠겨있지 않다면 임계구역 잠금
}
release() {
lock = false; // 임계구역 작업이 끝났으니 잠금 해제
}
임계 구역과 동기화 과정
- 임계 구역 진입 전 확인 (`acquire()`)
- 프로세스는 임계 구역에 진입하기 전 `acquire()` 함수를 호출하여 임계 구역이 잠겨 있는지 확인한다.
- 만약 임계 구역이 잠겨 있다면, 임계 구역이 열릴 때까지 반복적으로 상태를 확인한다. 이 과정을 바쁜 대기(busy waiting)이라고 한다.
- 임계 구역 진입 및 작업 수행
- 임계 구역이 열려 있다면, 프로세스는 해당 구역을 잠그고 진입하여 작업을 수행한다.
- 임계 구역 해제 (`release()`)
- 작업이 완료되면 `release()` 함수를 호출하여 임계 구역을 해제한다.
- 이를 통해 다른 프로세스가 임계 구역에 접근할 수 있도록 허용한다.
임계 구역에 접근하기 위한 동기화 과정은 `acquire()`로 잠김 여부 확인 → 작업 수행 → `release()`로 해제의 단계를 거친다. 바쁜 대기는 성능 저하를 유발할 수 있으므로 효율적인 동기화 메커니즘을 고려해야 한다.
2. 세마포어 (semaphone)
좀 더 일반화도니 방식의 동기화 도구로 공유 자원이 여러 개 있는 경우에도 적용이 가능하다. 세마포어 종류 중 카운팅 세마포어를 지칭한다.
세마포어의 경우 상호 배제를 위한 동기화와 실행 순서 제어를 위한 동기화 모두 가능하다.
세마포어의 구성
세마포어는 철도 신호기에서 유래한 개념입니다. 그래서 다음과 같은 동작을 실행하게 된다.
- 가라는 신호를 받으면 (임계 구역에) 진행해도 좋다.
- 멈추라는 신호를 받으면 (임계 구역에) 진입해서는 안된다.
이런 세마포어는 전역 변수 한개와 함수 두 개로 구현이 가능하다.
- 변수 S : 임계 구역에 진입할 수 있는 프로세스의 개수(공유 자원의 개수를 나타내는 전역 변수)
- wait 함수: 임계 구역에 들어가도 괜찮은지, 기다려야 하는지 알려주는 함수
- signal 함수 : 임계 구역 앞에서 기다리는 프로세스에게 진입해도 된다고 신호를 주는 함수
wait()
// 임계 구역
signal()
세마포어의 구현과 동작방식
위 함수는 자세히 나타내면 다음과 같다.
wait() {
while ( S <= 0 ) // (1) 만일 임계구역에 진입할 수 있는 프로세스가 개수가 0이하라면
; // (2) 사용할 수 있는 자원이 있는지 반복적 확인
S-- // (3) 임계구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 S를 1감소시키고
// 임계구역에 진입한다.
}
signal() {
S++ // 임계구역에서의 작업을 마친 뒤 S 1 증가한다.
}
해당 코드를 활용하여 다음 과정을 이해해 보자.
과정을 요약한다면, 주어진 전역변수 S만큼 프로세스는 임계구역에 진입할 수 있고 `S=0`이 된다면 다음 프로세스는 대기해야 한다. 그런 다음, 임계구역에 들어간 프로세스가 작업을 종료하면 `S+1`되고 대기 중이던 프로세스가 진입하게 된다.
해당 방식의 문제점과 해결방안
위 과정은 뮤텍스 락과 마찬가지로 임계 구역 진입 확인로직이 무한히 돌아가는 바쁜 대기 형태이다. 이런 무한 대기 또는 무한 반복로 확인하는 과정은 불필요한 CPU 사이클이 낭비될 수 있게 된다.
이를 해결하기 위해 세마포어는 대기 큐와 프로세스 상태 전이가 활용되게 된다.
대기 큐를 사용하여 자원이 사용 중인 경우 프로세스를 큐에 넣고, 자원이 해제되면 큐에서 프로세스를 꺼내어 실행한다. 이 과정에서 프로세스 상태 전이가 활용된다.
프로세스는 자원을 기다리는 동안 `대기`상태로 전이되고, 자원이 사용 가능해지면 `준비`상태로 전이되어 CPU를 사용할 수 있게 된다. 이러한 상태 전이를 통해 CPU자원을 효율적으로 사용하고, 바쁜 대기문제를 해결할 수 있다.
구현 코드와 진행 방법
코드는 다음과 같다.
wait() {
S--;
if (S < 0) { // (1) 임계구역에 진입할 수 있는 프로세스가 없으면
enqueue(this); // (2) 현재 프로세스를 대기 큐에 추가하고
sleep(); // (3) 프로세스를 대기 상태로 전환
}
}
signal() {
S++; // (1) 임계구역에서의 작업을 마친 뒤 S를 증가
if (S <= 0) { // (2) S가 할당이 가능하면
process = dequeue(); // (3) 큐에서 프로세스를 꺼내
wakeup(process); // (4) 해당 프로세스를 준비 상태로 전환
}
}
`wait()`함수 실행 시 `S`값이 음수가 되면 더 이상 임계구역에 진입할 수 없는 상태이므로 대기규에 넣고 해당 프로세스를 `대기`상태로 전환한다. 그런 다음 `signal()`함수로 통해 임계구역 작업이 끝난 다면 `S+1`를 진행하고 그 `S`가 `0`보다 커지면 대기큐에 프로세스를 꺼내 `준비`상태로 전환시킨다.
코드를 동작으로 본다면 다음과 같고 `S=2`로 가정한다.
실행 순서 제어를 위한 동기화
여기까지가 상호 배제에 대한 내용인데 세마포어는 실행 순서에 대한 제어도 제공한다고 했다.
- 먼저 실행할 프로세스 뒤에 `signal`가 위치한다.
- 나중에 실행할 프로세스 앞에 `wait`가 위치한다.
다음과 같은 그림으로 표기되며, `P1 -> P2`순으로 진행됨을 나타낸다. P1의 경우 프로세스 앞에 막는 게 없으니 바로 임계구역에 진입하게 되고, P2의 경우 `wait`막고 있으니 바로 진입이 불가하며, P1이 끝나고 실행되는 `signal`이 실행되어야지만 진입이 가능하게 된다.
참조
https://fastcampus.co.kr/dev_online_newcomputer
초격차 패키지 : 현실 세상의 컴퓨터공학 지식 with 30가지 실무 시나리오 | 패스트캠퍼스
국내유일, 77시간 분량의 개발자를 위한 한 번에 끝내는 컴퓨터공학 (CS 지식) 강의를 확인하세요. 자료구조,알고리즘부터 디자인패턴, 클린코드까지 ! CS지식의 이론~실습뿐 아니라, 실제 실무에
fastcampus.co.kr
'Knowledge > 컴퓨터구조&운영체제' 카테고리의 다른 글
[운영체제] 동기화와 교착상태 - 4. 교착상태와 해결 방법 (0) | 2025.01.07 |
---|---|
[운영체제] 동기화와 교착상태 - 3. 조건 변수와 모니터(동기화 기법) (0) | 2025.01.07 |
[운영체제] 동기화와 교착상태 - 1. 동기화 (0) | 2025.01.06 |
[운영체제] CPU 스케줄링 - (2) CPU 스케줄링 알고리즘 (3) | 2024.12.30 |
[운영체제] CPU 스케줄링 - (1) 프로세스 우선순위와 스케줄링 큐 (2) | 2024.12.27 |