CS/운영체제(OS)

Monitor란?

hyunah 2022. 5. 10. 09:18

Monitor란?

프로세스 동기화를 구현하기 위해서 semaphore를 사용하는 것에는 몇 가지 문제가 있다. 우선 코딩하기가 쉽지 않고, 정확하게 작동한다는 것을 입증하기가 어렵다. 또한 한 번의 실수가 모든 시스템에 치명적인 영향을 미친다. V와 P의 순서를 바꾸어 쓰거나 P만 2번 쓴 경우 mutual exclusion이 깨지거나 deadlock 문제가 생길 수 있다.

 

이러한 문제를 해결하기 위해 사용하는 것이 Monitor이다. 

 

Monitor란 객체단위로 구성된 프로그램으로, 공유 데이터 멤버 변수와 그 변수들을 조작할 수 있는 함수들을 포함하고 있다. 모니터 내에서는 한 번에 하나의 프로세스만이 활동 가능하도록 구현되어 있어서 semaphore를 이용할 때처럼 직접 동기화 제약 조건을 명시적으로 코딩하지 않아도 되기 때문에 훨씬 간단하게 이용할 수 있다.

 

 

 

 

Monitor의 구성요소들

- entry queue : 모니터 내부에 순서대로 진입하기 위해 대기하는 큐이다.

 

- condition variable : 프로세스가 모니터 안에서 기다릴 수 있도록 하기 위해 이용하는 변수다. wait과 signal 연산에 의해서만 접근 가능하다. condition variable의 이름을 x라고 한다면 x.wait()을 invoke한 프로세스는 다른 프로세스가 x.signal()을 invoke하기 전까지 suspend된다.

 

- shared variable : 공유 데이터이다.

 

- procedure : 공유 데이터에 접근하기 위한 함수다.

 

 

 

 

 

Monitor를 이용한 Classic Synchronization Problem의 해결

문제 자체에 대한 추가적인 설명은 이 글을 참고하자.

 

Bounded-Buffer Problem

monitor bounded_buffer
{
    int buffer[N];
    condition full, empty;
    
    void produc(int x)
    {
        if there is no empty buffer
            empty.wait();
        add x to an empty buffer
        full.signal(); /*full 버퍼를 기다리고 있는 프로세스가 있다면 깨운다.*/
    }
    
    
    
    void consume(int *x)
    {
        if there is no full buffer
            full.wait();
        remove an item from buffer and store it to *x
        empty.signal(); /*empty 객체 내의 대기 큐에서 대기하고 있는 프로세스 하나를 깨운다.*/
    }
}

 

 

 

 

Dining Philosophers Problem

monitor dining_philosopher
{
    enum {thinking, hungry, eating} state[5];
    condition self[5];
    
    void pickup(int i){
        state[i] = hungry;
        test(i);
        if(state[i]!=eating)
            self[i].wait() /*먹을 수 없는 상황이라면 여기서 대기*/
    }
    
    
    void putdown(int i){
        state[i] = thinking;
        test((i+4)%5);
        test((i+1)%5);
    }
    
    
    void test(int i){
        if((state[(i+4)%5]!=eating) && (state[i]==hungry) && (state[(i+1)%5]!=eating)){
            state[i] = eating;
            self[i].signal(); /*wake up Pi*/;
        }
    }
    
    
    void init(){
        for (int i=0; i<5; i++)
            state[i] = thinking;
    }
}




Each Philosopher:
{
    pickup(i); /*enter monitor*/
    eat();
    putdown(i); /*entrer monitor*/
    think();
} while(1);