호우동의 개발일지

Today :

article thumbnail

1. 교착 상태 탐지(Deadlock Detection)

1.0.1. 시스템이 교착 상태 예방 혹은 방지 알고리즘을 사용하지 않는 경우

  • 다음 2가지 알고리즘들을 반드시 지원해야 한다.
    1. 교착 상태가 발생했는지 결정하기 위해 시스템의 상태를 검사하는 알고리즘
    2. 교착 상태로부터 회복하는 알고리즘

  • 탐지와 회복 방법은 필요한 정보를 유지하고 탐지 알고리즘을 실행 시간 비용이 든다.
  • 또한, 교착 상태로부터 회복할 때 내재하는 가능한 손실을 포함하는 오버헤드가 필요

 

 


2. 각 지원 유형이 한 개씩 있는 시스템


2.1. 대기 그래프(wait-for graph)

  • 해당 경우, 대기 그래프를 사용해서 교착 상태 알고리즘을 정의
    • 대기 그래프(wait-for graph) : 자원 할당 그래프의 변형
      • 대기 그래프를 얻는 방법
        • 자원 할당 그래프로부터 자원 유형의 노드 제거 및 적절한 간선들을 결합

(a) 자원 할당 그래프, (b) 대응되는 대기 그래프
(a) 자원 할당 그래프, (b) 대응되는 대기 그래프

  • 대기 그래프에서 T(i) → T(j)로의 간선
    → 프로세스 T(j)가 가지고 있는 자원들에 대해, 프로세스 T(i)가 그 자원이 필요하여 자원 방출 대기

    • T(i) → T(j)는 해당 자원 할당 그래프가 자원 R(q)에 대해
      두 개의 간선 T(i) → R(q)R(q) → T(j)를 포함하는 경우에만 대기 그래프에 존재

 

2.1.1. 대기 그래프의 특징

  • 대기 그래프는 종류마다 자원이 여러 개씩 존재하는 상황에서 사용할 수 없음
  • 대기 그래프가 사이클을 포함하는 경우에만 시스템에 교착 상태가 존재
  • 교착 상태 탐지를 위해
    1. 시스템은 대기 그래프를 유지할 필요가 있음
    2. 주기적으로 그래프에서 사이클을 탐지하는 알고리즘을 호출
      • 그래프 사이클 탐지 알고리즘은 O(n^2)의 연산을 요구
        • n : 그래프에 있는 정점(vertice)의 수

 

2.1.2. BCC 툴킷

  • Linux에서 사용자 프로세스가 Pthreads mutex 락과 관련된 잠재적 교착 상태 감지 도구 제공
  • BCC 도구 deadlock_detector
    • pthread_mutex_lock()ㅇpthread_mutex_unlock()
      함수 호출을 추적하는 검사점을 삽입하여 작동

      • 동작 과정
        1. 지정된 프로세스가 두 함수 중 하나를 호출
        2. deadlock_detector는 해당 프로세스의 mutex락에 대한 대기 그래프 구성
          → 그래프에서 사이클을 감지하면 교착 상태 가능성을 보고

 

 


3. 각 유형의 자원을 여러 개 가진 시스템

  • 해당 방식은 시시각각 내용이 달라지는 자료 구조를 사용

3.1. 사용하는 자료구조

  • Available : 각 종류의 자원이 현재 몇 개가 가용한 건지를 나타내는 벡터(크기 m)
  • Allocation : 각 스레드에 현재 할당된 자원의 개수를 나타내는 행렬(크기 n * m)
  • Request : 각 스레드가 현재 요청 중인 자원의 개수를 나타내는 행렬(크기 n * m)
    • Request [i][j] == k : 현재 T(i)가 R(j)를 k개 요청 중임을 뜻함

 

 


4. 해당 탐지 알고리즘의 원리

  • 가능한 모든 할당 순서를 조사해 보는 방식
  • 가정
    • Work와 Finish는 크기가 m과 n인 벡터
    • Work = Available로 초기값을 준다.
    • i = 0, 1, …, n-1에 대해 Allocation(i) ≠ 0이면, Finish [i] = false
      • 그렇지 않으면 Finish [i] = true

  • 동작 과정
    1. 아래 두 조건을 만족시키는 i 값을 찾는다. 찾을 수 없다면 3번으로 이동
      • Finish [i] == false
      • Request(i) ≤ Work

    2. Work = Work + Allocation(i)
      Finish [i] = true
      → 이후 1번으로 이동

      • 시스템이 스레드 T(i)의 자원을 회수하는 이유
        • Request(i) ≤ Work로부터 프로세스 T(i)가 교착 상태에 빠져 있지 않음을 확인
          → 해당 프로세스가 작업을 마치기 전까지 더 이상의 추가적인 자원을 필요로 하지 않음
          → 작업을 마치면 T(i)은 가지고 있던 모든 자원을 반납하고 시스템을 떠난다.

          • 해당 가정이 틀렸다면 교착 상태는 다음에 발생함
            → 이 탐지 알고리즘의 다음 차례 때 교착 상태를 탐지할 수 있다.

    3. 어떠한 값 i에 대해 Finish [i] == false이면, 이 시스템은 교착 상태에 빠져 있는 것
      • T(i)가 교착 상태에 빠져있다.
      • 이때의 i 값 → (0 ≤ i < n)

  • 이 탐지 알고리즘을 실행하는 데는 m * n^2개의 연산이 필요

 


4.1. 해당 시스템 예시

4.1.1. 교착상태가 발생하지 않는 경우

시스템의 현재 상태
시스템의 현재 상태

  • 가정
    • 다섯 개의 스레드 (T0 ~ T4)까지 존재
    • 시스템에 A, B, C 세 가지 종류의 자원이 있다.
      • A 자원 = 7개
      • B 자원 = 2개
      • C 자원 = 6개
    • 시스템의 현재 상태는 위의 표에 나와 있다.

  • 해석
    • 이 시스템은 교착 상태에 처해있지 않다.
      • 알고리즘을 돌려보면 <T0, T2, T3, T1, T4> 순서로 작업을 다 끝낼 수 있다.
        • 이때 모든 i에 대해 Finish [i] == true를 성립한다.

 

4.1.2. 교착 상태가 발생하는 경우

  • 위 과정에서 T2가 C 자원을 한 개 더 요청하는 경우

T2가 C 하나 요청
T2가 C 하나 요청

  • 시스템이 교착 상태에 빠지게 된다.
    • T0의 자원을 회수한다고 해도, 다른 프로세스들이 요구하는 자원을 충족시킬 방법 X
      → T1, T2, T3와 T4가 교착 상태에 빠지게 된다.

 

 


5. 탐지 알고리즘 사용


5.1. 탐지 알고리즘은 언제 사용하는가?

  • 2가지 관점에 달려있음
    1. 교착 상태가 얼마나 자주 일어나는가?
    2. 교착 상태가 일어나면 통상 몇 개의 스레드가 거기에 연루되는가?

 

 


5.2. 교착 상태가 자주 일어나는가?

  • 교착 상태가 자주 발생한다면 탐지 알고리즘도 자주 돌려야 한다.
    • 교착 상태가 된 스레드로부터 자원을 회수하기 전에는 해당 자원을 아무도 쓰지 못함
    • 시간이 지날수록 교착 상태에 연루되는 스레드의 수가 증가할 수 있음

 


5.3. 교착 상태가 발생하면, 몇 개의 스레드가 거기에 연루되는가?

  • 교착 상태가 발생하는 시점
    → 스레드가 자원 요청을 했는데, 그 요청이 즉시 만족되지 못하는 시점

    • 극단적인 방법으로는 스레드 요청이 즉시 만족되지 못할 때마다 탐지 알고리즘을 돌림
      • 교착 상태에 연루된 스레드와 교착 상태를 야기한 장본인 스레드도 알 수 있음
      • But, 자원을 요청할 때마다 탐지 알고리즘을 호출하는 것은 높은 오버헤드 발생

  • 자원이 여러 종류가 있다면 한 자원에 대한 요청이 그래프상에서 사이클을 만드는 결과 초래 가능
  • 오버헤드를 줄이는 대안 → 지정된 시간 간격
    • 예를 들어, 1시간에 한 번씩 또는 CPU의 이용률이 40% 이하일 때만 탐지 알고리즘 호출

  • 탐지 알고리즘을 임의의 시간에 호출하면 안 되는 이유
    • 자원 그래프가 여러 개의 사이클을 포함할 수 있게 됨
      → 어느 스레드가 교착 상태를 야기한 장본인인지 알 수 없게 되어버림

 

 


6. 교착 상태로부터 회복

  • 탐지 알고리즘이 교착 상태 존재한다고 가정 → 여러 대안의 처리 방법이 존재
    1. 교착 상태 발생을 운영자(operator)에게 통지해, 운영자가 수작업으로 처리하는 것
    2. 시스템이 자동으로 교착 상태로부터 회복하게 하는 것

 

6.0.1. 교착 상태를 깨뜨리는 2가지 방법

  1. 순환대기를 깨뜨리기 위해 단순히 1개 이상의 스레드를 중지(abort)
  2. 교착 상태에 있는 하나 이상의 스레드들로부터 자원을 선점(preempt)

 

 


7. 프로세스와 스레드의 종료(Process and Thread Termination)

7.0.1. 프로세스/스레드 abort를 위해 사용하는 2가지 방법

  • 2가지 방법 모두 종료된 프로세스에게 할당되었던 모든 자원 시스템을 회수
  • 교착 상태 프로세스를 모두 중지
    • 해당 상태는 교착 상태의 사이클을 깨뜨리지만, 비용이 크다.
    • 비용이 큰 이유
      • 해당 프로세스가 오랫동안 연산했을 가능성이 있음
      • 이들 부분 계산의 결과들을 반드시 폐기해야 함
        → 이후 다시 계산을 해야 함

  • 교착 상태가 제거될 때까지 한 프로세스씩 중지
    • 각 프로세스가 중지될 때마다 교착 상태 탐지 알고리즘을 호출하고,
      프로세스들이 아직도 교착 상태에 있는지 확인
      • 상당한 오버헤드를 유발함.

 

7.0.2. 프로세스 중지가 어려운 이유

  • 프로세스가 파일을 갱신하는 도중인데 그 프로세스를 중지했을 경우
    → 해당 파일은 부정확한 상태가 되어버림

  • 프로세스가 mutex락을 점유한 상태로 공유 데이터를 갱신하는 도중 중지한 경우
    → 시스템은 락 상태를 사용 가능한 상태로 복구해야 함

 

7.0.3. 중지 프로세스 선택 결정을 위한 요인

  • 부분 종료 방식을 사용할 경우
    → 교착 상태 프로세스들 중에 어느 프로세스를 중지해야 할지 결정해야 함
    → 프로세스들을 중지시켰을 때 유발되는 비용이 최소인 프로세스들을 중지시켜야 함

  • 프로세스 결정을 위한 요인
    1. 프로세스의 우선순위가 무엇인지
    2. 지금까지 프로세스가 수행된 시간과 지정된 일을 종료하는데 더 필요한 시간
    3. 프로세스가 사용한 자원 유형의 수
      • 예 : 자원들을 선점하기가 단순한지 여부

    4. 프로세스가 종료하기 위해 더 필요한 자원의 수
    5. 얼마나 많은 수의 프로세스가 종료되어야 하는지

 


8. 자원 선점(Resource Preemption)

  • 교착 상태가 깨어질 때까지 프로세스로부터 자원을
    계속 선점해 다른 프로세스에 줌으로 교착 상태 제거

 

8.0.1. 자원 선점 방식에서 고려해야 할 3가지 사항

  • 희생자 선택(selection of a victime) : 어느 자원과 프로세스들이 선점될 것인가?
    • 비용을 최소화하기 위해서 선점의 순서를 결정해야 함
    • 비용 요인
      • 교착 상태 프로세스가 점유하고 있는 자원의 수
      • 교착 상태 프로세스가 지금까지 실행하는데 소요한 시간 등

  • 후퇴(rollback) : 프로세스로부터 자원을 선점하려면, 그 프로세스를 어떻게 해야 하는가?
    • 필요한 자원이 부족하기 때문에 교착 상태에 있는 프로세스를 정상 실행할 수 없다.
      → 이 프로세스를 안전한 상태로 후퇴시키고, 그 상태로부터 다시 시작해야 함

    • 후퇴의 가장 간단한 해결안 - 프로세스를 중지시키고 재시작하는 것
      • 완전히 후퇴시키는 방식
      • 해당 방식은 실행하는 모든 프로세스의 상태에 대한 많은 정보를 유지할 것을 필요로 함

    • 프로세스를 딱 교착 상태를 깨뜨릴 수 있을 정도로 후퇴시킨다면 더 효과적

  • 기아 상태(starvation) : 기아 상태가 발생하지 않는 것을 어떻게 보장할 것인가?
    • 자원들이 동일한 프로세스로부터 항상 선점되지 않다는 것을 어떻게 보장할 것인가?
    • 희생자의 선택이 시스템에서는 동일한 프로세스가 항상 희생자로 선택될 수 있음
      → 그 결과 자신의 태스크를 영원히 완료하지 못하는 기아 상태에 있게 될 수 있다.

    • 프로세스가 단지 (작은) 한정된 시간 동안만 희생자로 선정된다는 것을 반드시 보장해야 함
    • 일반적인 해결 방법 : 비용 요소에 후퇴의 횟수를 포함하는 방법