[운영체제] 대충 넘어가는 교착상태

Robert.Yang·2023년 4월 15일
1

OS

목록 보기
14/22
post-thumbnail

이 포스트는 널널한 개발자님의 강의를 듣고 작성한 글입니다.

대충 넘어가는 교착상태(DeadLock)

사전에 미리 말하면 저번 포스트에 했던 모니터구조로 Queue를 구성하여 설계하면 DeadLock은 일어날 일이 없다.

교착상태의 예시로 북한과 미국을 들 수 있는데 북한은 핵을 보유하지만 돈이 없다. 미국은 돈이 많아서 북한한테 '핵 그만 개발하면 돈 줄께'라고 요청을 하지만 북한은 '돈부터 먼저 주면 그만 할께'라고 하는 상태가 교착상태이다. 그래서 이런 경우는 진행 혹은 진전이라는 것이 존재하지 않고 이대로 영원히 멈춘 상태이다. 즉, 다음 액션을 취할 수 없는 상태이다. 그런데 여기서 DeadLock이 발생하기 위한 전제조건이 나와있다.

  1. 상호배제 : 예시로 화장실 혹은 휴지자원을 점유하고 대기
  2. 비선점 : 임계구간 처리할 때까지 계속 wait 상태
  3. 점유와 대기 : 배타적
  4. 원형대기 : 순환구조

예를 들어보자. 비선점형 상황에 자원이 화장실 혹은 휴지가 있다고 해보자. 어떤 사람이 화장실을 들어가 Lock을 걸고 볼일을 본다고 해보자. 이 볼일을 보는 구간이 임계구간인데 만약 휴지라는 자원이 화장실에 없는 경우에 휴지라는 자원이 있을 때까지 wait상태로 빠진다. 또한, 밖에 화장실이라는 자원을 기다리는 사람이 있는데 그 사람은 휴지가 있다고 해보자. 이런 상황이 DeadLock이다.

즉, 여기서 대전제가 성립이 되는데 휴지든 화장실이든 어떤 주체가 얻을려고 하면 얻을 수 있는데 한번 얻으면 그것에 대해 비선점 형태를 취한다. 즉, 자신의 임계구간 처리가 끝날 때까지 계속 이 형태를 취한다. 그래서 그 동안에 wait상태가 된는데 중요한 것은 요소가 2가라는 것이다.

임계구간에 영향을 주는 요소가 n개가 되면 논리적 복잡도가 생긴다. 그래소 요속 늘수록 안 좋고 이 요소는 최소화하는 것이 바람직하다.

DeadLock은 생각보다 쉽게 발생하지 않는다. DeadLock 발생상황을 생각해서 미리 동기화처리를 잘하면 되고 보통은 초보 개발자한테 벌어지는 일이지 그게 아니라면 쉽게 발생되지 않는다.

어떤 프로세스 내에 자원을 n개의 스레드가 동시에 접근하면 경쟁조건이 발생되고 진입할 때 DeadLock이 발생되기도 한다. 근데 중요한 것은 이 때 스레드는 프로세스 내 속하게 되는데 이 때 DeadLock을 해결하는 방법이 스레드를 하나 더 만들어서 다른 스레드 상태를 감시하게 하면 되는 것이다. 감시하는 스레드 상태가 계속 wait상태인지 얼마나 오래되었는지 감시하면 되고 대응은 발생하면 그 wait상태 스레드를 kill한다. 그리고 다른 스레드로 재시작을 하면 되는데 이때, kill하기 전에 memory Dump를 떠서 CallStack을 Dump를 해서 무엇때문에 wait상태가 되었는데 분석, 즉 Stack Tracing을 하면 어느정도 해결이 가능해진다.

wait라는 것은 프로세스 내 스레드들이 wait걸때는 무한정이라는것이 존재한다. 하지만 프로세스 수준으르로 확장하면 다음과 같다.

user-mode-application단에 n개의 프로세스가 있다고 해보자. 하드웨어에는 드라이버가 있고 커널요소도 존재할 것이다. 여기서 중요한 것은 디바이스를 제어하는 디바이스 드라이버가 있는데 이때 디바이스가 프린터라고 해보자. 근데 어느 프로세스가 프린터와 연결하고자 프린터를 추상화한 파일이 있을텐데 이 프로세스가 open을 했다고 해보자. 즉, open을 했다는 소리는 이 파일에 대해 Lock이 걸린다는 것인데 그러고 나서 파일에 대해 ~write()라는 System Call이 발생하고 프린터에 출력으로 이어진다.

근데 문제는 이 프로세스가 프린터를 100장을 해야하는데 어떤이유로 50장을 하고 suspend상태가 되버렸다. 그러면 결국 프린터를 추상화한 파일이 Lock이 걸린상태가 유지되므로 다른 프로세스는 접근이 안되고 wait상태가 될 것이다. 그럼 OS는 이 상황을 어떻게 할까? OS는 프로세스들을 계속 조사해서 일정시간 응답이 없는 프로세스들은 죽었다고 생각하고 이 프로그램을 죽이겠냐는 alert창을 띄워주고 yes를 누르면 그 프로세스는 죽는다. 그리고 Lock이 걸린 파일은 OS가 강제로 회수하게 된다. 그래서 다른 프로세스들이 진입이 가능해진다.

그래서 OS는 이렇게 자원관리를 해주고 프로세스를 통제해주는 중대한 역할을 해준다. 그리고 wait상태에도 무한대가 아니라 일정시간을 주게 되어있는데 보통 일정시간을 주면 일정시간 * 일정 횟수 + @만큼 시도하는데 계속 fail이 뜨면 메시징 처리를 하게 된다.

그래서 이런것들을 동기화할때 kernel Object중에 Mutex를 쓰는데 이 Mutex를 쓸때도 보통 시간을 같이 명시한다. 요즘은 OS가 좋아져서 프로그램들이 user-mode에서 동작하다가 죽어버리면 그 자원들을 알아서 회수해준다.

profile
모든 것을 즐길 줄 아는 개발자, 양성빈입니다.

0개의 댓글