교착상태(deadlock)는 프로세스가 리소스를 점유하고 놓아주지 않거나, 어떠한 프로세스도 리소스를 점유하지 못하는 상태가 되어 프로그램이 멈추는 현상을 말한다.
시스템 모델
시스템은 경쟁하는 프로세스들 사이에 분배되어야 할 유한한 자원들로 구성이되며, 여러 프로세스들을 해당 자원을 점유하기 위해 서로 경쟁 구도에 놓여있다. 메모리 공간, CPU 주기, 파일, 입출력 장치 등이 이러한 자원 유형이 예이다. 동기화 도구들(mutex, semaphore)도 시스템 자원 이다.
스레드는 다른 프로세스의 자원을 사용할 수 있으며 이러한 자원 사용으로 인해 교착 상태가 발생할 수 있다. 단. 이는 커널의 문제가 아니다(OS측에서 감시를 대신 한다). 스레드가 자원을 사용하기 위해서는 반드시 요청을 해야 하고 사용 후에는 반드시 방출해야 한다
정상적인 작동 모드아래에서, 프로세스는 다음 순서로만 자원을 사용할 수 있다.
1. 요청: 스레드는 자원을 요청한다. 요청이 즉시 허용되지 않으면(예를 들어, mutex lock을 다른 스레드가 가지고 있는 경우), 요청 스레드는 자원을 얻을 때까지 대기해야 한다. (system call)
2. 사용: 스레드는 자원에 대해 작업을 수행할 수 있다(예를 들어, 자원이 mutex lock이라면, 스레드는 자신의 임계구역에 접근할 수 있다.).
3. 방출: 스레드가 자원을 방출한다. (system call)
교착상태 특징
교착상태 필요조건
- 상호 배제(mutual exclusion): 한 번에 프로세스 하나만 해당 자원을 사용할 수 있다. 사용 중인 자원을 다른 프로세스가 사용하려면 요청한 자원이 해제될 때까지 기다려야 한다.
- 점유 대기(hold-and-wait): 자원을 최소한 하나 보유하고, 다른 프로세스에 할당된 자원을 점유하기 위해 대기하는 프로세스가 존재해야 한다.
- 비선점(no preemption): 이미 할당된 자원을 강제로 빼앗을 수 없다.
- 순환 대기(circular wait): 대기 프로세스의 집합이 순환 형태로 자원을 대기하고 있어야 한다.
자원 할당 그래프
교착상태는 시스템 자원 할당 그래프라고 하는 방향 그래프로 더욱 정확하게 기술할 수 있다. 이 그래프는 정점(vertex) V의 집학과 간선(edge) E의 집합으로 구성된다. 정점 V의 집합은 시스템 내의 모든 활성 스레드의 집합인 T = {\(T_{1}, T_{2}, ...,T_{n}\)}과 시스템의 모든 자원 유형의 집합인 R = {\(R_{1}, R_{2}, ...,R_{n}\)}으로 이루어져 있다.
프로세스 간의 관계를 그래프로 도식화해 보면 데드락이 발생할지 예상할 수 있다. 만약 그래프에 순환 고리가 있다면 데드락 위험이 있다는 의미가 된다. 순환 고리가 있다고 무조건 데드락이 발생하는 것은 아니지만, 순환 고리가 없으면 절대로 데드락이 발생하지 않는다.
교착상태 예방
데드락을 방지한다는 것은 데드락 발생 조건 중 하나를 만족시키지 않음으로써 데드락이 발생하지 않도록 하는 것이다.
- 자원의 상호 배제 조건 방지 : 적어도 하나의 자원은 공유가 불가능한 자원이어야 한다. critical section problem을 해결하기 위해서는 이 조건을 만족해야 하므로, 공유되는 자원이 있다면 이 조건을 만족시킬 수 밖에 없다. 그러나 어떤 자원들은 근본적으로 공유가 불가능하기 때문에 상호배제 조건을 거부함으로써 교착 상태를 예방하는 것은 불가능하다.
- 점유 대기 조건 방지 : 스레드가 자원을 요청할 때마다 다른 자원을 보유하지 않도록 보장한다. 한 프로세스가 실행되기 전 모든 자원을 할당시키고, 이후에는 다른 프로세스가 자원을 요구하도록 한다. starvation 문제가 생길 수 있다.
- 비선점 조건 방지 : 리소스를 점유하고 있는 프로세스가 다른 리소스를 요청했을 때 즉시 리소스를 사용할 수 없다면 점유하고 있던 리소스를 내놓는다.
- 순환 대기 조건 방지 : 자원들의 순서를 정하고 프로세스들은 이 순서를 지켜 요청하도록 함으로써, 사이클이 발생될 소지를 없게 만든다.자원의 낭비와 무한 대기를 발생 시킬 수 있다.
이러한 조건을 방지해서 데드락을 예방하는 방법은 시스템의 처리량이나 효율성을 떨어트리는 단점 이 발생할 수 있다.
교착상태 회피
교착상태를 피하는 것은 교착상태가 발생할 것 같을 때는 아예 리소스를 할당하지 않는 것 이다
시스템의 프로세스들이 요청하는 모든 자원을, 데드락을 발생시키지 않으면서도 차례로 모두에게 할당해 줄 수 있다면 안전 상태 (safe state)에 있다고 한다.
그리고 이처럼 특정한 순서로 프로세스들에게 자원을 할당, 실행 및 종료 등의 작업을 할 때 데드락이 발생하지 않는 순서를 찾을 수 있다면, 그것을 안전 순서 (safe sequence)라고 한다.
반면 불안정 상태는 안정 상태가 아닌 상황을 말한다. 즉, 데드락 발생 가능성이 있는 상황이며, 교착 상태(데드락)는 불안정 상태일 때 발생할 수 있다. 불안정 상태가 교착 상태보다 좀 더 큰 집합이다.(즉, 교착 상태가 불안정 상태의 부분집합)
회피 알고리즘은 자원을 할당한 후에도 시스템이 항상 Safe state에 있을 수 있도록 할당을 허용하자는 것이 기본 특징이다. 교착상태 가능성은 포인터로 자원 할당 그래프를 구현해 판단한다. 만약 리소스 타입이 여러 개라면 은행원 알고리즘(banker's algorithm)을 사용한다.
은행원 알고리즘 (banker's algorithm)
다익스트라가 제안한 기법으로, 어떤 자원의 할당을 허용하는지에 관한 여부를 결정하기 전에,미리 결정된 모든 자원들의 최대 가능한 할당량을 가지고 시뮬레이션 해서 Safe state에 들 수 있는지 여부를 검사한다. 즉, 대기중이 다른 프로세스들의 활동에 대한 교착 상태 가능성을 미리 조사하는 것이다.
은행원 알고리즘의 자료구조
- Avaiable: 각 형태별로 사용 가능한 자원수(사용 가능량)을 표시하는 길이가 m인 벡터. Available[j] = k이면, j번째 자원을 k개 사용할 수 있다는 의미이다.
- Max: 각 프로세스 자원의 최대 요청량(최대 요구량)을 표시하는 n*m 행렬. Max[i,j] = k이면, 프로세스 \(P_{i}\)는 자원 \(R_{j}\)를 최대 k개까지 요청할 수 있다는 의미이다.
- Allocation: 현재 각 프로세스에 할당되어 있는 각 형태의 자원수(현재 할당량)을 정의하는 n*m 행렬. Allocation[i,j] = k이면, 프로세스 \(P_{i}\)는 자원 \(R_{j}\)를 k개 할당받고 있다는 의미이다.
- Need: 각 프로세스에 남아 있는 자원 요청(추가 요구량)을 표시하는 n*m 행렬. Need[i,j] = k이면 프로세스 \(P_{i}\)는 자신의 작업을 종료하려고 \(R_{j}\)를 k개 더 필요하다는 의미이다.
은행원 알고리즘 동작 순서
프로세스 \(P_{i}\)가 자원을 요청하게되면 다음과 같은 동작이 일어난다.
STEP1: Request(i) <= Need(i)이면 다음 단계로 이동하고 그렇지 않으면 프로세스가 최대 요청치를 초과하기 때문에 오류 상태가 된다.
STEP2: Request <= Available이면 다음 단계로 넘어가고, 그렇지 않으면 자원이 부족하기 때문에 \(P_{i}\)는 대기한다
STEP3: 시스템을 다음과 같이 수정하여 요청된 자원을 프로세스 \(P_{i}\)에 할당한다.
이후 안전 상태인지, 불안전 상태인지 검사한다.
STEP1: Work와 Finish의 길이가 각각 m과 n인 벡터라고 하자. Work = Available, Fininsh[i]=False, i=1,2,...n으로 초기화한다.
STEP2: 다음 조건을 만족하는 i 값을 찾는다 i값이 없다면 step4로 이동한다.
STEP3: 다음을 수행하고 step2로 이동한다.
STEP4: 모든 i값에 대해 Finish[i] == true이면 이 시스템은 안전 상태에 있다.
은행원 알고리즘 예시
교착상태로투어 회복
먼저 시스템이 데드락 예방이나 회피법을 사용하지 않았을 때, 데드락이 발생할 수 있으니 여기에서 회복하기 위해 데드락을 탐지하고, 회복하는 알고리즘을 사용한다.
탐지 기법
Allocation, Request, Available 등으로 시스템에 데드락이 발생했는지 여부를 탐색한다. 즉, 은행원 알고리즘에서 했던 방식과 유사하게 현재 시스템의 자원 할당 상태를 가지고 파악한다.이 외에도 자원 할당 그래프를 통해 탐지하는 방법이 있다.
회복 기법
프로세스를 1개 이상 중단시키기
- 교착 상태에 빠진 모든 프로세스를 중단시키는 방법 : 계속 연산중이던 프로세스들도 모두 일시에 중단되어 부분 결과가 폐기될 수 있는 부작용이 발생할 수 있음
- 프로세스를 하나씩 중단 시킬 때마다 탐지 알고리즘으로 데드락을 탐지하면서 회복시키는 방법 : 매번 탐지 알고리즘을 호출 및 수행해야 하므로 부담이 되는 작업일 수 있다.
어떤 프로세스를 종료시킬지 정하는 것이 중요하다(경제적인 문제). 여기에는 몇가지 판단 기준이 있다
- 프로세스의 중요도
- 프로세스가 얼마나 오래 실행됐는가
- 얼마나 많은 리소스를 사용했는가
- 프로세스가 작업을 마치기 위해 얼마나 많은 리소스가 필요한가
- 프로세스가 종료되기 위해 얼마나 많은 리소스가 필요한가
- 프로세스가 batch인가 interactive한가
자원 선점하기
프로세스에 할당된 자원을 선점해서, 교착 상태를 해결할 때까지 그 자원을 다른 프로세스에 할당해 주는 방법. 교착상태를 해결하기 위해 선점을 사용한다면 아래의 사항들을 고려해야 한다.
- 희생자 선택(Selecting a victim): 어떤 프로세스를 종료시킬 지 결정해야한다.
- 후퇴(Rollback): 교착상태가 발생하기 전 안전 상태로 되돌린다. 어디로 후퇴할 지를 잘 정해야 한다. 확실한 방법은 완전히 후퇴시키고 재시작 하는 것이다. 교착 상태를 깨뜨릴 수 있을 정도록 후퇴시킬 수 있다면 효과적이지만, 프로세스 상태에 대한 많은 정보를 필요로 한다.
- 기아 상태(Starvation): 계속 같은 프로세스가 victim이 될 수 있다. 이 경우 기아(Starvation) 문제가 발생한다. 프로세스가 작은 한정된 시간 동안만 희생자로 선정된다는 것을 보장해야 한다.
'운영체제' 카테고리의 다른 글
[운영체제] 페이징(Paging), TLB (0) | 2021.09.27 |
---|---|
[운영체제] 연속 메모리 할당 (0) | 2021.09.22 |
[운영체제] 동기화 도구들 (뮤텍스, 세마포어, 모니터) (0) | 2021.09.08 |
[운영체제] CPU 스케줄링 (0) | 2021.09.06 |
[운영체제] 스레드(Thread), 스레드 모델 (0) | 2021.09.01 |