박종훈 기술블로그

운영체제 6장 동기화 도구들 - 연습문제 풀이

공룡책 (Operating System Concepts) 10th

개인적인 생각이므로 틀린 답변일 수 있습니다.


6.1

6.4절(동기화를 위한 하드웨어 지원 - Hardware support for synchronization)에서 인터럽트를 자주 비활성화하면 시스템 클록에 영향을 줄 수 있다고 언급했다. 왜 이런 일이 발생할 수 있고 그러한 영향을 최소화할 수 있는 방법에 대해 설명하라.

일단 6.4절이 아니다. 6.2절이다. 이거 찾느라 한참 걸렸다. (번역 오류가 아니다 원본에서 잘못 적은 것이다.) 문제에서 가리키는 부분은 다음과 같은 내용이다.

다중 처리기에서 인터럽트를 비활성화하면 시간이 많이 걸릴 수 있다. 이 메시지 전달은 각 임계구역으로의 진입을 지연시키고 시스템 효율성을 떨어뜨린다. 또한 클록이 인터럽트로 업데이트되는 경우 시스템 클록에 미치는 영향도 고려해야 한다.

인터럽트는 여러 목적을 위해 사용된다.
따라서 동기화 목적으로 인터럽트 발생을 막는다면 인터럽트를 사용해야 하는 다른 시스템 동작에 영향을 줄 수 있다.
따라서 인터럽트 처리 시간을 최소화 해야한다.

6.2

바쁜 대기(busy waiting) 라는 용어의 의미는 무엇인가? 운영체제에는 어떤 다른 대기가 있는가? 바쁜 대기를 완전히 피할 수 있는가? 여러분의 답을 설명하라.

바쁜 대기(busy waiting)는 특정 공유자원에 대하여 두 개 이상의 프로세스나 스레드가 그 이용 권한을 획득하고자 하는 동기화 상황에서 그 권한 획득을 위한 과정에서 일어나는 현상이다. (wiki) 반복문을 통해 조건이 충족될 때 까지 대기하게 된다. 이를 피하기 위해 대기중인 프로세스를 휴면 상태로 전환한 후 사용할 수 있게 되면 깨우는 방식을 취한다.

6.3

스핀락이 단일 프로세서 시스템에 적합하지 않지만 다중 처리기 시스템에서는 종종 사용되는 이유를 설명하라.

단일 프로세서 에서는 락을 하고 있으면 다른 것을 하지 못하기 때문에 적합하지 않다.
그러나 멀티 프로세서 에서는 여러개의 프로세스가 있을 수 있고 한 프로세스에서 다른 프로세스의 상태를 수정할 수 있기 때문에 특정 상황에서 락을 해야 하고 동시에 문맥 교환을 하지 않기를 원하는 경우에 종종 사용될 수 있다.

6.4

wait() 및 signal() 세마포 연산이 원자적으로 실행되지 않으면 상호 배제가 위반될 수 있음을 보여라.

원자적으로 처리되지 않는다면, 현재 공유 자원에 접근 가능한지 아닌지 여부를 잘 못 판단할 수 있게 된다. 예를들어 세마포의 값이 1인 상황에서 wait() 이 2번 호출되었다 가정하자. 이때 wait()이 원자적으로 실행되지 않으면 wait() 호출한 2 곳에서 모두 접근이 가능할 수 있는 상황이 생기게 된다.

6.5

이진 세마포를 사용하여 n개의 프로세스 간에 상호 배제를 구현하는 방법을 설명하라.

do {
    wait(mutex);
    /* critical section */
    signal(mutex);
    /* remainder section */
} while (true);

Remainder : 나머지

6.6

경쟁 조건은 많은 컴퓨터 시스템에서 가능하다. deposit(amount)와 withdraw(amount)의 두 가지 함수를 사용하여 계좌 잔고를 유지하는 은행 시스템을 고려해 보자. 이 두 함수는 은행 계좌 잔고에서 예치 또는 인출될 금액을 인자로 전달받는다. 남편과 아내가 은행 계좌를 공유한다고 가정하자. 남편은 withdraw() 함수를 호출하고 아내는 deposit() 함수를 병행하게 호출한다. 어떻게 경쟁 조건이 발생할 수 있는지 설명하고 경쟁 조건이 발생하지 않도록 하려면 무엇을 해야 하는지 설명하라.

경쟁 조건(race condition) : 공학 분야에서 경쟁 상태란 둘 이상의 입력 또는 조작의 타이밍이나 순서 등이 결과값에 영향을 줄 수 있는 상태를 말한다. (wiki)

예를 들어 현재 통장에 100 만원이 있고
남편은 10만원을 넣고
아내는 10만원을 출금한다고 해보자

deposit을 나누어 쪼개보면 다음과 같을 것이다.

temp = current_account_amount
temp = temp + amount
current_account_amount  = temp

마찬가지로 withdraw를 나누어 쪼개보면 다음과 같을 것이다.

temp = current_account_amount
temp = temp - amount
current_account_amount  = temp

이러한 상황에서
남편이 temp = current_account_amount 부분을 수행하면
temp 는 100만원이 된다.
이 상태에서 잠시 인터럽트가 발생되어서 작업이 멈췄다고 가정하자.

작업이 멈춘 상태에서 아내가 withdraw를 처리하면
통장 잔고는 90만원이 된다.

이후 남편의 작업이 이어서 진행되면
기존의 입력값에서 이어서 진행되므로 아래와 같은 연산을 처리하게 된다.

temp = 100,0000
temp = 100,0000 + 100,000
current_account_amount  = 100,0000

이렇게 되면 통장 잔고는 110,0000 만원이 되어버린다.

해결책은 확실하게 상호 배제 가 되어야 한다.