이번 주차는
▶ Chapter 12 프로세스 동기화
▶ Chapter 13 교착 상태 이다.
먼저 Chapter 12 프로세스 동기화를 살펴보자.
동시다발적으로 실행되는 프로세스들은 공동의 목적을 올바르게 수행하기 위해 협력해야 한다. 이러한 프로세스들은 실행 순서와 자원의 일관성을 보장해야하므로 동기화돼야 한다.
여기서 프로세스 동기화란, 프로세스들 사이의 수행 시기를 맞추는 것이다.
수행 시기를 맞춘다는 것은 실행 순서 제어와 상호 배제를 의미한다.
1. 실행 순서 제어: 프로세스를 올바른 순서대로 실행하기
2. 상호 배제: 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기
* 실행의 흐름을 갖는 모든 것은 동기화의 대상이 된다.
상호 배제에 대해 좀 더 알아보자.
상호 배제는 공유가 불가능한 자원의 동시 사용을 피하기 위한 알고리즘이다. 이것을 상호 배제를 위한 동기화라고 하며 생상자와 소비자 문제를 대표적인 예시로 꼽을 수 있다.
[ 생산자와 소비자 문제 예제 코드 ]
https://github.com/kangtegong/self-learning-cs/blob/main/producer_consumer/producer_consumer.md
동시에 접근이 안되는 자원은 무엇일까?
- 동시에 실행하면 문제가 발생하는 자원에 접근하려는 코드 영역을 임계 구역이라고 한다.
- 동시에 실행되는 프로세스들이 공동으로 사용하려는 자원은 공유 자원이라고 하며 이는 전역 변수 / 파일 / 입출력 장치 / 보조기억장치 등이 될 수 있다.
두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 하며, 먼저 진입한 프로세스의 작업이 마무리 될 경우에 기다리던 프로세스가 임계 구역에 진입할 수 있다.
잘못된 실행으로 인해 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 발생하는 문제를 레이스 컨디션이라고 한다. 해당 문제가 발생하면 일관성이 깨질 수 있다.
레이스 컨디션이 발생하는 근본적인 이유는 무엇일까?
=> 컴퓨터는 고급 언어가 아닌 저급 언어를 실행한다. 따라서 고급 언어가 여러 줄의 저급 언어로 변환되어 고급 언어 한 줄을 실행하는 과정에서 문맥 교환이 일어날 수 있다는 점이다.
운영체제는 임계 구역 문제를 3가지 원칙 하에 해결한다.
1. 상호 배제 : 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어올 수 없다.
2. 진행 : 임계 구역에 어떤프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
3. 유한 대기 : 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가 임계 구역에 들어올 수 있어야 한다.
=> 상호 배제를 위한 동기화를 위해서는 이 3가지 원칙이 반드시 지켜져야 한다.
프로세스의 동기화는 어떻게 이루어질까?
프로세스 동기화를 위한 대표적인 도구에 대해 알아보자.
1. 뮤텍스 락
=> 자물쇠 기능을 코드로 구현한 것이다. 임계 구역에 진입하는 프로세스는 뮤텍스 락을 이용해 임계 구역에 자물쇠를 걸어둘 수 있다.
- 자물쇠 역할 : 프로세스들이 공유하는 전역 변수 lock
- 임계구역을 잠그는 역할 : acquire 함수
- 임계구역의 잠금을 해제하는 역할 : release 함수
# acquire 함수란, 임계 구역에 진입하기 전에 호출하는 함수 이다. 임계 구역이 잠겨 있으면 열릴 때까지 임계 구역을 반복적으로 확인한다. 열려 있으면 임계 구역을 잠근다.
--> 잠겨 있는지 쉴 새 없이 반복하며 확인하는 대기 방식을 바쁜 대기라고 한다.
# release 함수란, 임계 구역에서의 작업이 끝나고 호출되는 함수로 현재 잠긴 임계 구역을 열어주는 함수이다.
2. 세마포
=> 뮤텍스 락과 비슷하나 세마포는 공유 자원이 여러 개 있는 상황에서도 적용이 가능한 동기화 도구이다.
[ 세마포를 이용한 상호 배제를 위한 동기화 기법 ]
- 임계 구역에 진입할 수 있는 프로세스의 개수 : 전역 변수 S
- 임계 구역에 들어가도 좋을지. 기다려야 할지. 알려주는 wait 함수
- 기다리는 프로세스에 이제 가도 된다는 신호를 주는 signal 함수
* 세마포는 바쁜 대기 대신 더 좋은 방법을 사용한다.
- wait 함수는 사용할 수 있는 자원이 없을 경우, 해당 프로세스 상태를 대기 상태로 만든다. 그리고 해당 PCB를 세마포를 위한 대기 큐에 넣는다.
- 임계 구역의 작업이 끝나고 다른 프로세스가 signal 함수를 호출하면 signal 함수는 대기 중인 프로세스를 대기 큐에서 제거하고, 준비 상태로 변경한 뒤 준비 큐로 옮긴다.
[ 세마포를 이용해 프로세스의 순서를 제어하는 방법 ]
- 세마포의 변수 S를 0으로 두고 먼저 실행할 프로세스 뒤에 signal 함수를 붙인다.
- 다음에 실행한 프로세스 앞에 wait 함수를 붙인다.
3. 모니터
=> 세마포에 비해 사용자가 사용하기 훨씬 편리한 도구이다.
[ 상호 배제를 위한 동기화 ]
- 모니터는 공유 자원 & 공유 자원에 접근하기 위한 인터페이스(통로)를 묶어 관리한다.
* 프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근하도록 한다.
- 공유 자원에 접근하고자 하는 프로세스를 큐(모니터 진입 위한 큐)에 삽입한다.
- 큐에 삽입된 순서대로 하나씩 공유 자원을 이용한다.
[ 실행 순서 제어를 위한 동기화 ]
=> 특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위한 조건 변수를 사용한다. 조건 변수로는 wait와 signal 연산을 수행할 수 있다.
- wait는 호출한 프로세스의 상태를 대기 상태로 전환하고 일시적으로 조건 변수에 대한 대기 큐에 삽입하는 연산이다.
* 해당 큐는 모니터에 이미 진입한 프로세스의 실행 조건이 만족될 때까지 잠시 중단되어 기다리기 위해 만들어진 큐이다.
상호 배제를 위한 큐 != 조건 변수에 대한 큐
- wait 연산으로 일시 중지된 프로세스는 다른 프로세스의 signal 연산을 통해 실행이 재개될 수 있다.
다음으로 Chapter 13 교착 상태를 알아보자.
교착 상태란, 일어나지 않을 사건을 기다리며 진행이 멈춰 버리는 현상을 말한다.
교착 상태는 자원 할당 그래프를 통해 표현할 수 있다.
1. 프로세스는 원으로, 자원의 종류는 사각형으로 표현한다.
2. 사용할 수 있는 자원의 개수는 자원 사각형 내 점으로 표현한다.
3. 프로세스가 어떤 자원을 할당받아 사용 중이면, 자원에서 -> 프로세스를 향해 화살표를 표시한다.
4. 프로세스가 어떤 자원을 기다리고있다면, 프로세스에서 -> 자원으로 화살표를 표시한다.
=> 교착 상태가 발생한 상황은 자원 할당 그래프가 원의 형태를 띄고 있다.
이번에는 교착 상태가 발생하는 근본적인 이유에 대해 알아보자.
* 교착 상태가 발생하는 조건에는 상호 배제, 점유와 대기, 비선점, 원형 대기가 있다. 해당 조건 중 하나라도 만족하지 않으면 교착 상태가 발생하지 않는다. 하지만 모두 만족한다면 교착 상태가 발생할 가능성이 있다.
1. 상호 배제 : 교착 상태의 근본적인 원인은 해당 자원을 한 번에 하나의 프로세스만 이용 가능하기 때문이다.
2. 점유와 대기 : 프로세스가 하나의 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다리는 상태이기 때문이다.
3. 비선점 : 어떤 프로세스가 다른 프로세스의 자원을 강제로 빼앗지 못하는 비선점 자원이기 때문이다. 비선점 자원은 자원을 이용하는 프로세스의 작업이 끝나야만 이용할 수 있다.
4. 원형 대기 : 프로세스들과 프로세스가 요청 및 할당받은 자원이 원의 형태를 이루었기 때문이다. \
이러한 교착 상태를 운영체제는 어떻게 해결할까?
운영 체제는 교착 상태를 예방하거나 회피할 수 있으며, 검출 후 회복할 수 있다.
1. 교착 상태 예방 : 이는 교착상태 발생 필요 조건 4가지 중 하나를 충족하지 못하게 하는 방법과 같다.
a. 자원의 상호 배제 제거 : 모든 자원을 공유 가능하게 만든다는 것과 같다. 따라서 실현하는 것은 무리다.
b. 점유와 대기 제거 : 특정 프로세스에 자원을 모두 할당하거나 아예 할당하지 않는 방식으로 배분한다. (단)=>당장 자원이 필요해도 기다릴 수 밖에 없는 프로세스, 사용되지 않으면서 오랫동안 할당되는 자원을 다수 양산하기에 자원의 활용률이 낮아진다. 결국 많은 자원을 필요로 하는 프로세스가 무한정 기다리는 기아 현상을 야기할 수 있다.
c. 비선점 조건 제거 : 선점하여 사용할 수 있는 일부 자원에는 효과적이다. 하지만 모든 자원이 선점 가능한 것은 아니므로 범용성이 떨어진다.
d. 원형 대기 조건 : 모든자원에 번호를 붙이고 오름차순으로 자원을 할당한다. (단)=>컴퓨터 시스템 내 수많은 자원에 번호를 붙이는 것은 간단하지 않으며, 특정 자원의 활용률이 떨어질 수 있다.
2. 교착 상태 회피 : 프로세스들에 배분할 수 있는 자원의 양을고려하여 교착 상태가 발생하지 않을 정도의 양만큼 자원을 배분하는 방법이다.
* 안전 상태 : 교착 상태가 발생하지 않고 모든 프로세스가 정상적으로 자원을 할당받고 종료될 수 있는 상태
* 불안전 상태 : 교착 상태가 발생할 수도 있는 상황
* 안전 순서열 : 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서
(따라서 안전 상태는 안전 순서열대로 프로세스들에 자원을 배분하여 교착 상태가 발생하지 않는 상태 / 불안전 상태는 안전 순서열이 없어 교착 상태가 발생할 수 있는 위험이 있는 상태이다.)
3. 교착 상태 검출 후 회복 : 교착 상태 발생을 인정하고 사후에 조치하는 방식이다.
=> 운영체제는 프로세스들이 자원을 요구할 때마다 그때그때 모두 할당하고, 교착상태 발생 여부를 주기적으로 검사한다. 그리고 교착 상태가 검출되면 그 때! 다음과 같은 방식으로 해결한다.
a. 선점을 통한 회복 : 교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식
b. 프로세스 강제 종료를 통한 회복 : 교착 상태에 놓인 프로세스를 모두 강제 종료하거나 / 교착 상태가 없어질 때까지 한 프로세스씩 강제 종료한다. (=> 전자는 한 방에 해결할 수 있으나 작업 내역을 잃을 가능성이 있고, 후자는 작업 내역을 잃는 프로세스는 최대한 줄일 수있으나 교착 상태가 없어졌는지 여부를 확인하는 과정에서 오버헤드를 야기한다.)