본문 바로가기
공부/운영체제

운영체제6 Process Synchronizaiton

by 맑은청이 2020. 7. 3.
728x90
반응형

이번 챕터에서는 프로세스 동기화에 대해 보겠습니다.

순서는 아래와 같습니다. 

 

이 챕터에서 가장 중요한 건 '어떤 공유된 리소스, 메모리에 접근할 때 어떻게 제대로 된 동작을 시킬까?'

동기화를 어떻게 시킬까하는 문제입니다. 

critical-section problem(임계구역문제) 가 나오는데 이 개념을 어떻게 실행시킬건지에 대해 이야기할 겁니다. 

소프트웨어 기법, 하드웨어 기법으로 살펴볼겁니다. 


Background

 

요새는 코어가 싱글이든 멀티이든 Concurrently 방식으로 멀티 프로세스가 동작이 됩니다. 

이 때 이런 프로세스 들은 shared data 에 접근을 할 겁니다. 

여기서 어느 시점에 읽고 어느 시점에 업데이트할 거에 따라서 프로세스에게 원하는 결과를 주는가 아니면 잘못된 결과를 줄 수 도 있을 겁니다. 이 때문에 임계구역문제가 나왔고 이를 어떤 식으로 제공을 할거냐를 이 챕터에서 이야기 할 겁니다. 

 

 

 

좀 더 자세한 예시로 과거에도 나왔던 Producer Consumer problem 에 대해 이야기 해봅시다.

Producer 가 쓸때 무작정 쓰면 안 됩니다.  쓰기 전에 버퍼가 다 차지 않았는지 확인을 해야합니다.

다 찼다면 쓸 수가 없으니 기다리는 상태가 지속이 될 겁니다.

item을 buffer 에 넣으면 Counter 를 하나 늘립니다. 

이 때 Consumer 쪽에서 읽으면 counter 가 줄어들게 됩니다. 이러면 Producer가 쓸 수 있겠죠.

그리고 카운터가 0이면 Consumer 는 읽을 데이터가 생길 때까지 기다립니다

 

 

정상적인 동작을 위해 어떻게 해야할까요. 여러가지 문제가 생기는데 확인해 보겠습니다.  

 

 

 

  • Race Condition 발생

카운터 변수들은 다음과 같이 동작 할 겁니다. 

이러면 정상적으로 작동하는 거처럼 보입니다. 

하지만 이러한 동작을 따로 한다고 생각해봅시다. 

두개의 프로세스가 공유된 자원, Counter 을 따로따로 다뤘을때 다음과 같은 상황이 발생하게 됩니다.

카운터를 5라고  가정해보겠습니다. 

S1 과 S2 사이를 보면 아직 counter ++ 이 갱신이 안된 상황에서 counter -- 과정이 시행되는 것을 볼 수 있습니다. 

S4에서는 counter 이 6

S5 에서는 counter 4 가 되어버립니다. 

이처럼 최종 실행 결과 프로세스나 thread의 실행 순서에 의해 달라져 버립니다. 이 때문에 '프로세스 동기화' 가 필요한 겁니다. 

 

 

그래서 나온 개념이 Critical Section Problem 입니다. 

프로세스의 어느 부분이 아주 중요하다 판단하고 이를 임계구역(Critical Section으로 정했습니다. 

임계구역 내에서는 변수를 업데이트하고 파일을 쓰고 그러는데

가장 중요한 특징은 이 임계구역에서는

반드시 '하나의 프로세스'만이 접근을 할 수 있다는 겁니다. 

 

 

Critical Section problem 

은 이 임계구역이 실행되는 프로토콜을 만드는 겁니다. 

 

이 임계구역에 들어가기 전이 entry section(진입구역) 이고 나가는 쪽은 exit section(퇴출구역)입니다. 그리고 나머지를 Remainder section(나머지 구역)이라고 합니다. 

 

atomic - 쪼개질 수 없다. 

critical section 이 중간에 잘못되면 뚝 끊기는 게 아니라 처음부터 다시 실행이 됩니다. 

 

 

Algorithm for Process Pi

turn 이라는 공유 변수가 0으로 초기화 되어있습니다. Pi가 critical section으로 들어 갈 수 있다는 말입니다.

while 문에서 i가 차례가 되면 critical section으로 들어가는 거죠. 

 

 

 

 Critical-Section Problem Solution 에서 다음의 세개는 반드시 보장이 되어야만 합니다. 

 

1. Mutual Exclusion(상호배제) - 두 프로세스가 동시에 뭔갈 하면 안된다는 의미입니다. critical section 

 

2. Progress(진행) - critical section을 차지한 프로세스가 없어서 어떤 프로세스가 진입 가능한 상황. 이때 진입하고자 하는 process들이 있다면 이 들 모두가 진입하기 위해 무기한 기다려서는 안됩니다. -> Deadlock avoidance 필요

 

3. Bounded Waiting(한계대기) - 현재 어떤 프로세스 A가 임계 구역 진입을 요청한 후 A 자신은 진입이 허용 될때 까지

이때 다른 프로세스들이 임계 구역에 진입하는 횟수에 있어서 제한이 있어야합니다. (아니면 A는 집입하지 못하게 됨. 

만족 못할 경우 기아 발생)

 

 

 


구체적으로 Critical Section을 실행하는 방법에 대해 알아보겠습니다. 

 

SW기반 방법 - Algorithm1

보면 프로세스 두개와 turn 이라는 게 있습니다. turn shared variable 입니다.

repeat를 보니 반복이 되고 있다는 걸 알 수 있죠. turn =1 이면 P1 에 차례구나하고 기다립니다. 이러면 Critical Section 에 한 명만 접근을 할 수 있습니다. 자기가 Critical Section 에서 벗어나면 다른 프로세스가 Section 에 접근할 수 있도록 turn을 바꿔줍니다. 

 

Progress requirement(진행 요구사항) 를 충족하지 못합니다. Remainder Section이 굉장히 클 때 문제가 생깁니다. 

아래는 문제가 생기는 상황입니다.

이러면 P0 이 Critical section 에서의 실행을 끝내고 turn 을 넘겨 주는데 P0의 large RS 때문에 turn 을 0으로 바뀌지 못하고 그러면 P1이 아래의 wait until turn == 1 를 충족시키지 못하기 때문에 block 이 되어 버립니다.

P1 이 RS 를 끝내기 전까지 CS 로 들어가지 못하는 겁니다.  

->매우 비효율적 

 

이는 CS에 진행되는 프로세스가 없고 진입하고자 하는 프로세스가 있다면 이건 'Progess' 라는 문제점이 유발되는 겁니다. 

 

 

 

 

SW 기반 방법 - algorithm2

 

 

그림이 좀 바뀌었습니다. 공유 데이터가 두개가 생겼네요. 

하지만 결론부터 말하자면 여기도 Mutual Exclusion 은 만족하지만 progress requirement 를 만족시키지는 못합니다. 

flag는 깃발이라는 말입니다. 즉 이게 true 가 되면 'CS에 들어가고 싶다' 라는 의미 입니다. 

 

P0 쪽으로 보면 반복문에 flag[1] 이 1이면 기다립니다. 그리고 P1은 CS가 끝난 이유 깃발을 내립니다. 그리고 P0의 반복문이 끝남으로 flag[0] 를 true 로 바뀌어졌습니다. 이는 다른 프로세스가 진입하지 못하게 하는 겁니다. 이렇게 Mutual Exclusion 인거죠.

 

특별한 경우가 생길 수 있는데 이는 flag[0], flag[1]가 둘다 true 인 상황입니다. -> Deadlock(데드락)이 발생하게 됩니다. 

 

 

 

SW 기반 방법- Algorithm, Peterson's Solution 

 

이는 문제를 해결할 수 있는 알고리즘입니다!

 

여기서 두개의 프로세스가 두 Share Variable을 가지게 됩니다. 

 

int turn;

Boolean flag[2];

 

turn 과 flag값을 확인해서 CS 들어갈 조건을 정합니다. (조건 두개)

여기서 turn 에 값을 넣는 순간이 같이 실행이 되더라도 결국에는 turn 은 0과1 중 하나의 값으로 결정이 됩니다.

만약 한 프로세스가 CS을 끝내고 flag 값이 false 가 된다면 다른 프로세스의 조건문이 깨져서 CS 으로 들어가게 됩니다. 다음 그림과 같이.

Mutual exclusion 

: flag[0] = flag[1] = true 는 P0와 P1 이 CS에 들어가고자 하는 의도가 있음을 의미 

turn = i 이면 Pi 가 CS에 들어감 

 

Progress and bounded waiting requirements 

: Pi의 CS영역 진입 제한은 while(flag[j] == true && turn ==j) 때문 ①

 - Pj가 CS 진입 준비가 안되었거나(flag[j]  <- false) 혹은 j가 들어갈 순서 아니면 (turn != j), 자신 i가 CS 진입 가능.

->즉, whiel문 wait을 벗어나서 Pi는 CS에 진입

 

: Pj 는 자신의 flag[j] <- true 로 하고 CS 진입하고자 기다림(while문) ②③

  - 이때  turn == i 이라면 Pi의 CS 영역으로 진입하고, turn == j 이면 Pj의 CS영역에 진입

  - 한편 Pj는 CS영역 실행 후, flag[j] <- false 로 지정하여, 자신은 CS에서 나왔다는 것을 알림.

->이는 곧, 상대방 Pj가 CS에 진입하도록 만듦

 

 

 

 

 


이때까지 소프트웨어 기반의 동기화 기법인 Peterson에 대해 보았습니다.  

이제 하드웨어 기반의 동기화를 보겠습니다. 

 

기본적으로 lock 입니다. 

lock 을 얻은 session 만이 critical section 에 진입을 할 수가 있습니다. 아니면 하지 못합니다. 

지금까지는 turn 이나 flag 같이 소프트웨어 변수에 따라 조건 진입을 했는데 하드웨어서는 lock 기반의 동기화가 진행이 됩니다. 

 

처음에는 Uniprocessors , 즉 코어가 하나인 경우에서 동작이 되는 프로세스가 여러개 있다고 하면 여기서 한 프로세스가 진입을 하면 interrupts를 disable 해 버립니다. Uniprocessor는 그냥 프로세스가 쭉 실행이 되면 interrupts를 disable 시키면 다른 프로세스가 끼어들 수 없습니다. 

 

또한 특별한 atomic hardware instruction을 사용하는 방법이 있습니다. 

이 명령어 자체는 non-interruptible 해야합니다. 

 

대표적 사례 - test and set , compare and swap 

 

 

프로세스에서 진행되는 과정 

do {
	//CS에 들어가기 전에 lock
	acquire lock
    	critical section
    release lock //CS에서 나오면서 lock 을 품
    	remainder section
} while(TRUE);

여기에서 target의 주소를 알려주는 함수라고 생각하면 됩니다. 

test : 메모리 주소의 값 확인

set : target 주소에 값을 setting 

 

즉 test_and_set 는 '주소의 값을 확인하고 그 값을 setting

 

1. Executed atomically , 다른 개입없음

2. Returns the original value of passed parameter 

3. set the new value of passed parameter to "TRUE"

 

 

다음은 lock 이라는 변수가 어떻게 사용되는지를 봅시다.

 

test_and_set 으로 현재 lock 의 값이 무엇인지 알아줍니다. 

lock 이 0이면 CS 영역으로 들어간 후 false 를 해주고 만약 1이면 반복문을 계속 돕니다. 

다른 프로세스가 들어오지 않게 lock을 true 로 바꾸어 주는 거죠. 

 

 

 

이제 Compare_and_swap 명령어를 살펴보겠습니다. 이도 유사합니다. 

 

 

 

expected 는 기대되는 값이고 이게 값이랑 값으면 새로운 값으로 셋팅을 해준다는 의미입니다.

compare_and_swap 으로 lock 의 값을 봅니다.

만약 1이면 lock 이 되어 있기 때문에 계속 while 을 도는 겁니다. 만약 lock이 0이면 깨지니깐 CS값으로 들어갑니다. 

진입하자마자 lock 을 1로 바꾸어 다른 프로세스의 진입을 막습니다. 

 

 

이 기법에는 사실 문제가 있습니다. 그건 Bounded Waiting(한계대기) 를 충족시키지 못하는 겁니다 .

Bounded Waiting계속 CS로 진입을 하면 다른프로세스가 CS에 계속 못 들어가서 Waiting 을 하는 상황을 만들지 않는 겁니다. 

하지만 위의 상황에서 이를 방지하는 장치가 없습니다. 계속 기다리다가 들어갈 수 있게 하는 장치를 넣어 변형된 코드를 보겠습니다.

 

 

여기서 boolean waiting[n]; 은 false 로 초기화되어 있습니다. 

Pi가 waiting 하고 있으며 key 는 true 이며 CS 진입을 위해 test_and_set check 를 합니다.

lock이 false 값이면 (다른 Process에 의해 lock 되어 있지 않으면), key 가 false가 되어서 진입이 됩니다. 

자신은 CS에 진입하면서 lock을 1로 셋팅해 다른 프로세스에 진입을 막습니다. 

CS 영역 진입후 Pi 자신은 waiting 하지 않는다고 알립니다. 

 

 

CS에서 나오면서 다른 Pj 상태를 i + 1, 에서 i - 1 까지 순환하면서 check 합니다. 

waiting 하는 j 가 있으면 해당 j를 waiting[j] <- false 로 해여 P 를 진입가능하게 만들어 줍니다. 

자신은 lock을 해제합니다. 다른 Pj가 진입 가능하게 

 

이를 통해서 한정된 대기조건을 만족시킵니다. 

 

 

 

이 솔루션이 사실 좀 복잡합니다. 그렇기 때문에 간단한 Mutext Locks 에 대해 알아보겠습니다. 

이는 acquire()와 release()로 , 구조적 대칭으로 설계가 되어있습니다. 

 

acquire() : lock 을 얻음

release() : lock 반환

acquire() 함수를 보면 계속 busy 하게 기다리며 available 값을 확인하는 것을 볼 수 있습니다.

들어가는 순간 false 로 바꾸어 버립니다.

release()는 true 로 lock을 풀어주는 겁니다. 

이 두 함수는 atomic 해야합니다. 

 

하지만 이 코드에도 문제가 있었습니다.

바로 이 부분입니다. 계속 busy waiting 을 하기 때문에 CPU power 가 소비됩니다. 

 

 

 

 

 

 

Semaphore 

Mutex lock 보다는 좀 정교한 방식입니다. 

 

이는 P() 와 V() 로 이루어져 있는데요. 이건 네달란드로 P는 검사하다. V는 증가하다라는 의미를 담고 있습니다. 

하지만 저희는 일반적으로 wait()와 signal() 로 바꾸어 사용하도록 하겠습니다. 

S는 정수 값을 가집니다. 

 

두개의 프로세스가 있습니다.

입니다. 조건은 S1과 S2가 절대 동시에 실행되어선 안된다는 겁니다. 

즉 S1다음에 S2가 실행되는 것을 보장해야합니다. ->Semapore로 실행

 

이걸 어떻게 하는걸까요? 

P1 은 무조건 S1이 실행이 될겁니다. 

하지만 P2에서는 S2는 wait(synch) 다음에 실행이 되어야하죠. 

wait는 다음과 같은 함수 입니다.

synch 는 0으로 초기화 되어 있습니다. 

즉 S가 0이상 이하이면 wait가 걸려서 S2로 넘어갈 수가 없습니다. 

그래서 S1이 끝나고 나서 Signal 을 날려서 synch 값을 양수로 바꾸어 주는 겁니다 .

이렇게 동기화가 되는 겁니다. 

 

 

하지만 여기서도 'busy waiting' 이 발생이 됩니다. 하지만 여기서는 while이 어셈블리어로 3줄도 안되는 light 한 busy wait이라고 말할 수 있습니다. 

 

물론 이에 대한 또 다른 해결방법이 있습니다. 

 

이 문제를 해결하기 위해서는 while 로 busy waiting 하는게 아니라 waiting queue 에 집어넣고 scheduler 로 밖에 빼내는 형식으로 하면 됩니다. 

 

 

Semaphore Implementation with no busy waiting

 

위 예시처럼 P1이 진행이 될때 P2를 wait 함수로 busy waiting 해두는 게 아니라 waiting queue 에 넣으면 해당 프로세스가 waiting state 으로 갑니다. scheduler 가 다른 프로세스를 선택 실행해줍니다. 

그러면 어떻게 이 프로세스를 선택할 수 있을까요. 

이는 signal()의 wakeup() 에 의해 waiting state 을 ready state 으로 변경합나다. 그럼 Ready queue 에서 scheduling 이 됩니다. 

 

이러면 CPU 성능 방면을 봤을때 좋습니다.  

 

그럼 semaphore 는 각각의 waiting queue를 가집니다. 그리고 block 과 wakeup이라는 개념이 생깁니다.

 

block은 waiting queue 로 가는거고

wakeup은 이를 ready queue 로 옮겨주는 것입니다.  

 

 

 

S->value <= 0 라는 의미를 즉 기다리는 놈이 있으면 ... 이라는 뜻입니다. 그 후 기다리는 놈을 선택해서 wakeup 하는 겁니다. 

 

 


DeadlockStarvation에 대해 알아보겠습니다. 

결국 둘 다 실행이 안되는 겁니다. 

하지만 개념 상 조금 다릅니다. 

 

Deadlock의 정의는 다음과 같습니다.

 

이 부분이 중요합니다. Deadlock은 결국 하나의 waiting processes 에 의해 발생한다는 뜻입니다. 

 

 

Wait(S) 가 실행이 됩니다. 1 에서 -1 이니깐 0이 되겠죠. 

P1 에서 Wait(Q) 가 실행이 됩니다. 동일하게 0이 됩니다. 

P0 에서 wait(Q)을 넘을려면 0보다 커야합니다. 그러면 Signal(Q) 가 필요합니다. 근데 P1이 이를 해줍니다. 그러면 wait(S)를 signal(s) 로 1로 만들어줘야하는데 이러면 P0이 ... 

이렇게 절대 1이 될 수 없는 구조 , Deadlock 상황입니다.

->P0과 P1가 무한정 기다리는 상황

 

 

 

Starvation어떤 process가 계속 기다리는 상황입니다. (Deadlock은 전체가 기다리는 상황)

Priority Inversion(우선순위 역전문제) : 우선순위가 더 낮은 프로세스가 lock을 잡아내서 높은 우선순위의 프로세스가 실행되지 못하는 형태 


Classical Problems of Synchronization 

 

이제 지금까지 살펴본 동기화 schemes 을 사용해서 다음 문제들을 알아가 보겠습니다. 

 

1. Bounded-Buffer Problem (유한 버퍼 문제)

2. Readers and Writers Problem

3. Dining-Philosophers Problem( 식사하는 철학자)

 

 

  • Bounded-Buffer Problem 

n개의 buffer 즉 n개의 item 수

Semaphore 세개를 사용합니다. 

 

mutex(상호배제를 위한),

full(채워진 버퍼개수,지금은 0),

empty(비어진 버퍼개수, 지금은 n)

버퍼 full 에 접근 할 때 생산자와 소비자가 동시에 접근을 하면 안됩니다. 

그래서 mutex (상호 배제 기능 제공)을 사용하게 됩니다. 초기에는 접근이 가능하기 때문에 1로 설정해줍니다.

초기 Semaphore 상태

 

여기서 Producer 는 wait 로 빈 buffer slot 이 있을 때까지 기다립니다.

그리고 쓸때는 자기 자신만 접근을 해야겠죠?

그래서 wait(mutex)를 해버리는 거죠. 그리고 Buffer pool에 item 을 씁니다. 

 

Consumer 는 반대로 채워진 buffer 가 있는지를 보겠죠? full로.

읽을 때도 상호배제 상태에서 읽어야합니다. 

 

Bounded buffer problem, 간단하죠? 

 

 

 

 

  • Readers-Writers Problem 

Readers : 읽는 사람

Writers : 쓰는 사람 

 

Problem : 이 둘이 동시에 데이터에 접근하면 ? -> 엉망이 됨

그럼 상호배제 상태로 글을 읽고 써야합니다. 

 

다음과 같은 상황을 고려해야합니다. 

 

(1) First readers-writers problem

:Writer 가 공유 자원을 이미 사용하고 있지 않는 한 , Reader 들은 계속 Wait 할 필요 없이 자원을 잡을 수 있음. 

문제, Writer가 기아에 빠질 수 있음

 

(2) Second readers-writers problem

: Reader 는 두번째 우선순위, Write가 첫번째 우선! 

문제, Reader 가 기아에 빠질 수 있음 

 

 

(1) First readers-writers problem 해결책(Writer 기아가능)

-Writer 가 공유 자원을 잡지 못했다면, 기다리는 Reader 에게 기회 제공

-> 

Semaphore rw_mutex = 1 ( reader 와 writer 가 공유 -> 둘이 경쟁이라는 걸 의미) 

Semaphore mutex (read_count 상호배제 위해 존재) 

Semaphore read_count (현재 몇개의 프로세서들이 이 객체를 읽는지 알려줌)

Writer 입장에서는 wait(rw_mutex) 에 조건이 하나 더 들어가 있습니다. 'if(read_count == 1)' 입니다. 

이는 reader 가 여러 개 있을 때 writer 가 기아에 빠지지 않도록 reader 의 수를 적절히 제어해주고 있는 형태입니다. 

 

 

이 signal(rw_mutext)는 writer 에게 영향을 줍니다. 

 

 

 

 

 

 

  • Dining-Philosophers Problem

 

이 그림을 보면 의자가 5개에 5명이 앉습니다. 그리고 테이블 가운데 밥이 있습니다.

접시 옆에 젓가락 한개씩( 한 쌍 아닙니다.) 이 있네요 .

하지만 젓가락은 한 쌍으로 사용해야하죠? 

 

그래서 마냥 이 철학자가 젓가락으로 식사를 할려면  아래와 같이 젓가락을 집어야합니다. 

 

 

철학자는 한번에 한 젓가락만 들어올릴 수 있습니다.그니깐 오른쪽 젓가락 한개 집고 내려놓고 왼쪽 젓가락 집는 형태인거죠. 만약 오른쪽 젓가락 집을려고 했는데 옆자리 철학자가 쓸 수 있을 수도 있는거에요. 두개를 모아야하는데! 한개만 있으면 안되는거죠! 하지만 한 번에 한번씩만 젓가락을 들어올 릴 수 있다는 점입니다. 이해가 가시나요?

 

Shared data 

- bowl of rice(data set)

- 5 Semaphores : chopstick[5] 초기화 1

 

 

그림과 같다고 생각해봅시다. 

5번 철학자의 입장을 생각해 봅시다. 

 

wait(chopstickp[5]) 다섯번째 즉 자신의 오른쪽 젓가락을 기다립니다. 

그리고 이 Semaphore을 잡으면 (5 + 1)%5 = 1 , 왼쪽 젓가락을 기다립니다. 

그 다음은 'eat' 합니다. 

그리고 젓가락을 놓아야하니깐 Signal 로 차례로 놓습니다. 

 

여기서 문제는 'Deadlock'이 발생이 된다는 점입니다. 

생각만 하면 간단해요. 현재 모든 철학자가 왼쪽 젓가락을 왼손에 잡고 있다고 생각해봅시다. 그럼 현재 책상이 놓여진 젓가락이 없는데 다들 오른쪽 젓가락이 오길 기다리는 상태가 되니깐 Deadlock 이 걸릴 수 밖에 없는거죠.

 

 

이를 어떻게 해결할까요? 

방법1. 4명만 앉는다.

방법2. 양쪽 젓가락이 동시에 집을 수 있을 때 동시에 집어야한다. 

방법3. 짝수 자리 철학자는 왼쪽 홀수는 오른쪽을 들게 한다. 

 

 

 

Problems with Semaphores 

 

semaphore이 wait 와 signal 이 프로그램 전반에 산재에 있기 때문에 프로그래머 쓰기 힘듭니다. 

그래서 나온게 Monitor 입니다. 

Semaphore와 동일한 기능을 제공하고 사용하기 쉽습니다. 

 

특징

1. 지역변수는 monitor의 프로시저만 접근 가능, 외부 변수 접근 불가 

2. 프로세스는 monitor의 프로시저 중 하나를 호출해서 monitor로 들어감

3. 한순간 오직 하나의 process 만이 monitor 내에 존재, 즉 이미 monitor 사용중이면 다른 프로세스는 대기 

 

 

 

 

Monitors - 동기화 방법

 

Monitor이 멀티프로세스의 병행처리에 사용되려면 "동기화 방법" 도 제공해야합니다.

-> 조건 변수 제공 (cwait(c) , csignal(c) 로 접근, c -> 조건)

 

Monitor 의 wait, signal 은 Semaphore와는 좀 다른데 , 여기선 기다리는 process 가 없으면 해당 signal을 잃어버립니다. 

 

 

모니터의 특징은

- 상호배제 조건에 의해, 하나의 process만 진입가능합니다. 하나의 entry point 

이미 사용중이라면 다른 프로세스는 queue 에 block 이 됨.

Silberschatz, Balvin and Gagne

그리고 모니터 내부에서 조건 C1에서 걸린다면 큐로 들어가게 됩니다. (모니터 밖으로 가는겁니다.)

 

 

 

모니터 상세설명

- 모니터는 진입구가 '하나' 입니다. 

- 사용중이라면 queue 로 들어가게 됩니다. 

- 모니터 내부에서 수행 중이던 프로세스가 조건 c1 에 의해서 대기할 필요가 있습니다. cwait(c1) 이 호출되고 -> c1 queue에서 block 됩니다. 

- 조건이 변하면 monitor로 재진입합니다.

- 모니터 내부에서 수행중이던 프로세스가 조건 c1의 변화를 발견하면, csiginal(c1)을 호출합니다. 이는 c1 queue에서 대기중이던 프로세스를 깨웁니다. 

- urgent queue 는 모니터에서 수행되던 프로세스가 블록될 경우, 새로 진입하는 프로세스(queue of enterping processes)보다 더 높은 우선순위를 갖고 다시 실행되기 위해 사용 가능합니다. 

 

 

 

코드를 자세히 보겠습니다. 

다음은 Bounded-Buffer Producer/Consumer Problem을 모니터로 해결하는 코드 입니다.

append는 데이터를 쓰고자 하는 경우 입니다. Producer 는 직접 buffer 공간 접근을 할 수 없고 오직 monitor 의 append()를 호출하여 데이터 buffer 에 추가 합니다 .

cwait 로 notfull 인 상황을 기다립니다. full 이면 일시중지 해야합니다. 

이 때 다른 프로세스가 monitor로 들어갈 수 있습니다. 

그리고 버퍼가 차면 notempty signal 을 보내는 겁니다. 

take 함수도 비어 있지 않으면 사용하는 겁니다. empty 라면 take 하면 안되겠죠. 

 

 

 

 

Monitor Solution to Dining Philosophers

 

상황이 3개가 있습니다.

1. THINKING - 음식을 먹을지 말지 생각, 젓가락 안 집음

2. HUNGRY - 배고파서 CS 에 들어가고 싶어하는 상황

3. EATING - 젓가락을 가지고 있는 상황, CS에 들어가 있는 상황

 

다음은 내 양쪽이 다 EATING 상태가 아니고 나도 HUNGRY 인 경우 EATING 으로 갈 수 있다는 의미 입니다.

test 는 지금 내가 EATING 이 될 수 있는지를 의미합니다.

(3) 은 EATING 상태가 아니기 때문에 젓가락을 집지 못했으니깐 기다린다는 의미 입니다.

밥 다 먹고 이제 안 먹으니깐 THINKING 상태로 놔두는 겁니다. 

 

 

 

 

 


Alternative Approaches 

또다른 방법들에 대해 이야기를 해보겠습니다. 

1. Transactional Memory(TM)

2. OpenMP

3. Functional Programming Languages

 

 

 

Transactional Memory(TM)

: 특정 영역을 atomic 하게 수행될 수 있게 함

OpenMp


운영체제 챕터 6 끝났습니다. 

728x90
반응형

'공부 > 운영체제' 카테고리의 다른 글

운영체제8 Memory Mangement  (0) 2020.07.03
운영체제7 Deadlock  (0) 2020.07.03
운영체제5 CPU Scheduling  (0) 2020.06.21
운영체제4 Threads  (0) 2020.06.17
운영체제3 Processes  (1) 2020.06.14