** 뮤텍스란(Mutex)? **

“Mutual Exclusion 으로 상호배제라고도 한다. Critical Section을 가진 쓰레드들의 Runnig Time이 서로 겹치지 않게 각각 단독으로 실행되게 하는 기술입니다. 다중 프로세스들의 공유 리소스에 대한 접근을 조율하기 위해 locking과 unlocking을 사용합니다.

즉, 쉽게 말하면 뮤텍스 객체를 두 쓰레드가 동시에 사용할 수 없다는 의미입니다.

 

** 세마포어란?(Semaphore) **

세마포어는 운영체제 또는 커널의 한 지정된 저장장치 내 값으로서, 각 프로세스는 이를 확인하고 변경할 수 있습니다. 확인되는 세마포어의 값에 따라, 그 프로세스가 즉시 자원을 사용할 수 있거나, 또는 이미 다른 프로세스에 의해 사용 중이라는 사실을 알게 되면 재시도하기 전에 일정 시간을 기다려야만 합니다. 세마포어는 이진수 (0 또는 1)를 사용하거나, 또는 추가적인 값을 가질 수도 있습니다. 세마포어를 사용하는 프로세스는 그 값을 확인하고, 자원을 사용하는 동안에는 그 값을 변경함으로써 다른 세마포어 사용자들이 기다리도록 해야합니다.


*** 뮤텍스와 세마포어의 차이점 ***

1) Semaphore는 Mutex가 될 수 있지만 Mutex는 Semaphore가 될 수 없습니다.

(Mutex 는 상태가 0, 1 두 개 뿐인 binary Semaphore)

 

2) Mutex의 경우 Mutex를 소유하고 있는 쓰레드가 이 Mutex를 해제할 수 있습니다. 하지만 Semaphore의 경우 이러한 Semaphore를 소유하지 않는 쓰레드가 Semaphore를 해제할 수 있습니다.

 

3) Semaphore는 시스템 범위에 걸쳐있고 파일시스템상의 파일 형태로 존재합니다. 반면 Mutex는 프로세스 범위를 가지며 프로세스가 종료될 때 자동으로 Clean up된다.

 

★★★

가장 큰 차이점은 관리하는 동기화 대상이 갯수입니다. Mutex는 동기화 대상이 오직 하나뿐일 때,

 Semaphore는 동기화 대상이 하나 이상일 때 사용합니다.

★★★

 

[출처]: http://jwprogramming.tistory.com/13

'cs > os' 카테고리의 다른 글

#6-4. Process Synchoronization  (0) 2018.01.22
#6-3. Process Synchronization  (0) 2018.01.21
#6-2. Process Synchronization  (0) 2018.01.15
#6-1. Process Synchronization  (0) 2018.01.11
#5-3. CPU SCHEDULING  (0) 2018.01.09

#6-4. Process Synchoronization
: 프로세스 동기화에서 생기는 문제점 3가지를 알아보도록 하겠습니다.

 

 


* Bounded-Buffer Problem
: 버퍼의 크기가 유한

 

 

 

# 상황 설명
- Circular buffer 형태로 되어있다.
- 여러개의 Producer(생산자) 프로세스와
- 여러개의 Consumer(소비자) 프로세스가 있다.

 

# 역할
 - Producer : 공유버퍼에다가 데이터를 하나 만들어서 집어넣는역할.
 - Consumer : 데이터를 꺼내가는 역할
(원형 버퍼의 그림을 보면 주황색 색칠 부분은 producer가 데이터를 넣은것이고, 색칠 안된 동그라미는 consumer가 데이터를 쓴것.

 

???)

여기서 Synchronization과 관련해서 어떤문제들이 발생할까?

 

1) 공유 버퍼이기 때문에 생산자가 둘이 동시에 도착해서 동시에 데이터를 만들어 집어 넣으면 동기화 문제가 발생.
=> 공유 버퍼에 lock을 걸어서 동기화문제를 해결해야 한다.

 

2)공유 버퍼이기 때문에 소비자가 둘이 동시에 도착해서 동시에 데이터를 가져가면 동기화 문제가 발생.
=> 역시 공유 버퍼에 lock을 걸어서 동기화문제를 해결하도록 한다.

 

3) 버퍼가 유한(Bounded) 하기 때문에 생기는 문제
: 즉, 버퍼가 찼는데, 생산자(producer)가 도착하는 경우, 또는 버퍼가 비었는데 소비자(consumer)가 도착하는 경우.
=> producer는 버퍼가 가득 찼는지, consumer는 버퍼가 비었는지 체크 해줘야 한다.

 


----------------------------------------------------------
!!!)

 Semapore 를 이용해서 해결해야할 문제가 2가지가 있다.

 

 

1) 동시에 공유 버퍼에 접근하는것을 막기 위해서 lock을 걸었다가 푸는 작업.

2) 버퍼가 가득 차거나, 비었을 때를 알수 있게 counting Semapore가 필요하다.
----------------------------------------------------------

 

 

 

 

# 세마포어로 구현한 생산자, 소비자 문제


 

 


* Readers - Writers Problem

 

 

 

# 상황 설명

- 프로세스는 2종류(읽는 P, 쓰는 P)
- 공유 데이터 : DB

 

Sol)

Reader는 동시접근이 가능하게 하고,

Writer는 동시접근이 불가능하게 해야한다.


# 세마포어를 통한 문제 해결 코드

 

 

# Reader 부분 설명

 

1) 노란색 부분인 if(readcount == 1) P(db); 을 보면 1일때에만 db(스몰 db)로 lock을 걸어주게 되고, 1이 아니면 이미 lock이 걸려 있기 때문에 DB에 바로 들어갈 수 있다.

2) But, 여기서 readcount도 공유 변수 이므로 동시에 접근할 경우 동기화 문제가 발생할 수 있다. 그래서 mutex변수를 이용하여 readcount에 접근하는 부분에도 lock과 unlock을 걸어주도록 한다.


!!!)

그렇지만 Writer의 Starvation 현상이 발생한다.


readcount가 0이 되어야 V(db)로 lock이 풀리는데,

Reader가 너무 많아 지면 Writer는 Starvation 현상이 발생하게 된다.

 


* Dining - Philosopheres Problem (식사하는 철학자 문제)
:  2가지 업무가 있다. (생각하는 업무, 밥을 먹는 업무)

 

 

 

 

!!!)

노란색 코드 때문에 Deadlock이 발생할 수 있는 위험한 코드이다.


why))

 eat()에 들어가기 전에 모든 철학자가 P(chopstick[i])코드 때문에 자신의 왼쪽 젓가락을 들고 안놓게 된다... 그렇게 될 경우 아무것도 진행이 될 수 없는 Deadlock 현상이 발생하게 된다.

 그럼 어떻게 해결을 해야 할까?

 

 

 

 

 

 

# 식사하는 철학자문제를 세마포어로 해결한 코드

 

 

 

# 변수 설명
- semaphore self : 각각의 5명의 철학자가 젓가락 2개를 잡을수 있어서 젓가락 잡는 권한을 줄것이나 말것인가를 정하는 변수.

 ex>
 - self[1] = 0; // 1번 철학자는 젓가락 잡기 불가능.
 - self[3] = 1; // 3번 철학자는 젓가락 잡기 가능.

- mutex : state변수에 접근에 lock/unlock 을 위한 변수.

- test 함수 : 젓가락 잡을수 있는 권한이 있나?
 즉, 왼쪽 철학자랑 오른쪽 철학자가 먹고 있지 않고, 내가 hungry인 상태일때, 젓가락 잡을수 있는 권한 획득.


* 세마포어의 문제점

 

 


=> 세마 포어를 개발자가 잘 지키면 프로그램이 제대로 돌아가겠지만, 제대로 했는지 확인이 힘들다....

 

 

* Moniter
: 공유데이터를 접근하기 위해서는 모니터라고 정의된 내부에 프로시저를 통해서만 내부의 공유 데이터에 접근할수 있게 만들어 놓는것. 그리고 모니터가 원천적으로 내부에 프로시저가 동시에 여러개가 실행되지 않도록 만드는것.(=> 이렇게 되면 lock을 걸 필요가 없다.)

(프로그래밍 언어 차원에서 동기화 문제를 해결을하는 High-level Synchronization construct)

 

 


semaphore의 lock & unlock기능은 해결!!

 

???)
자원의 개수를 어떻게 셀까?

 

 

 

 

 

# 함수 설명

- wait() : 자원이 없으면 기다리게 하는 함수
- signal() : 접근을 다하고 빠져나갈 때 호출(invoke)하는 함수

 

 

 

* 모니터 내부 형태

 

 

 


* 모니터로 convert한 Bounded-Buffer & Dining - Philosopheres Problem
: 세마포어처럼 lock을 걸 필요가 없다.
(모니터 안에서 하나의 프로세스만 실행되기 때문에!!)

 

 

 

 

 

 

 

 


 

'cs > os' 카테고리의 다른 글

[1]. 세마포어와 뮤텍스  (0) 2018.01.22
#6-3. Process Synchronization  (0) 2018.01.21
#6-2. Process Synchronization  (0) 2018.01.15
#6-1. Process Synchronization  (0) 2018.01.11
#5-3. CPU SCHEDULING  (0) 2018.01.09

#6-3. Process Synchronization

 

cf > 추상 자료형 : 논리적으로 정의하는것이지, 실제로 컴퓨터에서 어떻게 구현되는지는 별개의 문제.

 

 

* Semapores
: 추상 자료형

 

 

 

 

# semapore 자료형은 p연산v연산이 존재하게 된다.

 

 

---------------------------------------------------------
???) Semapore라는것을 왜 사용 하는가?


공유 자원을 획득하고 반환하는것을 세마포어가 처리해준다!

 

p 연산 : 공유데이터를 획득하는 과정
v 연산 : 다 사용하고 나서 반납하는 과정.


=> p연산을 하면 lock을 거는 과정이고, v연산은 lock을 푸는 과정이다.
---------------------------------------------------------

 

 

# 세마포어 값은 Integer(정수) 값을 가지는데, 자원의 갯수를 의미 한다.

 


cf> p연산과 v연산은 atomic 하게 연산이 된다고 가정한다!

 


* Critical Section of n Processes
: critical section 문제에다가 semapore를 사용해보자.

 

 

 

# mutex 변수를 1로 놓고,

critical section에 들어가야 할때(lock을 걸때)에는 p연산을 해주고,

  critical section을 나올때(lock을 풀때)에는 v연산을 해준다.

=> 이렇게 되면 critical section문제가 자연스럽게 해결이 된다.


=> 즉, 세마포어를 통해서 프로그래밍을 해주면 개발자는 훨씬 간단한 프로그래밍을 할수 있다. (6-2에서 나왔던 알고리즘을 고려하지 않아도 된다)

 

But.. 누군가 critical section에 들어가 있다면 p연산에서 while문을 돌면서  기다리기 때문에 busy-waiting (= spin lock)이 해결 되지는 않는다...

 

 

cf> Block & Wakeup 방식 (=sleep lock)
: 누군가가 critical section에 있다면, 쓸데없이 while문을 도는(spin)하는 것이 아니라 blocked 상태에서 기다리는 방법!


* Block / Wakeup Implementation
: 세마포어 변수를 획득하지 못한 프로세스는 block상태에 두는것.

 

 

 

 

# 구체적으로 어떻게 구현되는지 살펴 봅시다!

 

 

 

# p 와 v에 들어있는 s는 세마포어 변수

 

v. p연산 : 자원을 획득하는 과정
 - 자원에 여분이 있다면 획득!
 - 자원에 여분이 없다면 block();

v. v연산 : 자원반납하고, 자원을 기다리면서 혹시 잠들어 있는 자원이 있다면 그 자원을 깨워주는 연산

 

???)

v연산에서 if(S.value <= ) { wakeup(P); }

를 보면 자원을 내놓았는(S.value++) 데에도 불구하고

S.value가 음수 인 경우는 block()된것이 많다는것이다.

그래서 wakeup() 으로 깨워준다.
 


=> busy waiting 방식과는 조금 다르다.
: busy waiting 방식에서는 단순히 자원의 갯수를 세는 경우였는데, block-wakeup방식은 조금 다르다. 
 block-wakeup방식에서는 단순히 세는것이 아니라 깨워야할 누군가가 있는지를 확인하기 위해 사용된다.

 

 

* 어떤 방법이 더 좋은 방법 일까?

 

 

 

# block / wakeup 하는 방법에도 overhead가 있다. critical section이 짧은 경우에는 busy - waiting도 괜찮다.


* Two Types of Semaphores
: 세마포어의 두가지 타입

 

 


* Deadlock and Starvation
: 세마포어를 사용할때 주의해야 원치 않는 문제

 

 

 

1) Deadlock :
: 상대방이 가진것을 기다리면서 자기것은 내놓지 않고, 서로 영원히 기다리는것을 DEADLOCK이라고 한다.

 

ex> 세마포어 S 와 Q, 두개가 있는데, 세마포어 두개를 모두 획득해야지만, 일을할수 있는 그런 환경.

P0순서에서 S를 획득했다. 그런다음에 P1에 차례가 넘어갔다.
P1순서애서 Q를 획득했다.


=> P0와 P1은 서로를 무한히 기다리게 된다.

 

=> 해결방법 : 자원을 획득하는 순서를 똑같이 맞춰주자. 즉, 모든 프로세스가 S먼저 획득하고 Q를 획득하게끔 해준다.

 

2) Starvation
: 특정프로세스만 자원을 받고, 나머지 프로세스는 무한히 기다리는 것.

 

 

 

 

 

'cs > os' 카테고리의 다른 글

[1]. 세마포어와 뮤텍스  (0) 2018.01.22
#6-4. Process Synchoronization  (0) 2018.01.22
#6-2. Process Synchronization  (0) 2018.01.15
#6-1. Process Synchronization  (0) 2018.01.11
#5-3. CPU SCHEDULING  (0) 2018.01.09

* 동기화 기본 코드




# 그림설명 : 임의의 프로세스의 code 소개.


 cf> critical section : 공유데이터를 접근하는 코드

     remainder section : 공유데이터를 접근하지 않음

     

     (entry, exit) section : lock을 거는 행위

     ???) 여러 프로세스가 동시에 critical section에 들어가는 것을 막는다. (이것이 동기화 개념!)



* Critical Section문제를 풀기 위해서 만족해야 할 조건 

: 크게 3가지가 있다.


 


# Mutual Exclusion : (entry, exit) section 부분.

 

  Progress : 코드를 잘 못 짜면 이러한 문제 발생.

  

  Bounded Waiting : 기다리는 시간이 유한해야 된다.(즉, starvation이 생기지 않아야 한다.)

  ex> cirtical section에 들어가고 싶은 프로세스가 3개가 있는데 2개만 들락날락 거리고

        나머지 한개는 마냥 기다리는 상황이 생겼을때 Bounded Waiting조건을 만족하지 못한다.

 

 


=> 이 3가지 조건을 만족하면서 lock을 잘 걸었다가 푸는 그런 알고리즘들을 알아보도록 하자!



* Algorithm 1 

: turn 교대가 포인트!!


 


cf>

1) P0를 위한 코드

 

1
2
3
4
5
6
7
8
9
10
11
do {
 
while(turn != 0); // 0이 아니면 못들어 간다.
 
critical section
 
turn = 1;   // citical section에서 빠져 나와서 다음 차례로 만들어준다.
 
remainder section
 
}while(1);
cs


2) P1를 위한 코드


1
2
3
4
5
6
7
8
9
10
11
do {
 
while(turn != 1);
 
critical section
 
turn = 0;
 
remainder section
 
}while(1);
cs


# turn이 0이면 0번 프로세스, 1이면 1번 프로세스!

# 위에 코드는 1번 조건인 Mutual Exclusion은 만족한다 (P0의 경우, while (turn != 0), turn = 1로 인해서)

But, 2번 조건인 Progress는 만족 x.


why??))

코드를 보면 한 프로세스가 critical 세션에서 나와야 지만 턴이 상대 차례로 변하게 된다. 근데 이런 프로세스의 critical section 빈도가 다를수 있다. 

극단적으로, P0는 critical section에 여러번 들어가고 싶은데, p1은 한번만 들어가고 안들어가도 된다. 이런 경우엔 P1이 한번만 들어가고 안들어가기 때문에 P0차례를 만들어주지 못한다. (차례를 바꿔 주려면 일단 들어갔다가 나올때 바꿔줌으로..)

P0는 영원히 못들어가게 된다...


=> turn을 교대로만 해주면 안되겠다.. 다른방법을 생각해 보자!



* Algorithm 2 

: flag가 포인트


 


# Critical Section에 접근하는 방법


[단계 1] Critical Section에 들어가려면 flag를 true로 바꾼다.


[단계 2] 상대방 flag를 chk한다.

(IF, 상대방 flag가 true가 있으면 기다린다.)


[단계 3] 들어갔다 나올때 flag를 false로 바꿔준다.


# 이 알고리즘의 문제??

: Critical Section에는 아무도 안들어 갔는데 P0와 P1이 동시에 true로 한 경우. 이 경우에는 끊임없이 서로 양보하는 상황이 발생.


=> flag를 이용하는 알고리즘도 Progress는 충족시키지 못했다.... 다른 방법을 생각해 보자!



* Algorithm 3 (Perterson`s algorithm)

: turn과 flag 모두 사용.


 


# Critical Section에 접근하는 방법


[단계 1] Critical Section에 들어가려면 flag를 true로 바꾼다.


[단계 2] turn을 상대방 turn으로 바꿔 놓는다.


[단계 3] turn과 상대방 flag를 chk한다. 

(IF, 상대방의 flag가 true이고, turn도 상대방이면 기다린다.)


[단계 4] 들어갔다 나올때 flag를 true로 바꿔준다.


=> 조건 3가지(Mutual Exclusion, Progress, Bounded Waiting) 모두 만족


But, 이 코드의 문제점이 있다.

 


 

# Spin Lock(= Busy Waiting)

ex> p0한테 cpu 할당 시간이 왔을때, while (flag [j] && turn == j);에서 빠져 나가지 못 할 경우도 있다.

      결국 자신의 cpu할당 시간에 3번째 구간에서 chk만하다가 끈나는 경우.

=> 즉, 비효율 적인 방법을 나타냄

 


 

cf> instruction 단위로 time sharing이 일어나서 cpu 사용권이 바뀌기 때문에 이런 문제가 발생한다!

=> Spin Lock의 해결법은 나중에 알아보도록 하자!

 


 


!!!) 사실은 H/W 적으로 하나의 Instruction만 주어지면 이러한 critical section문제는 아주 쉽게 해결이 된다. => Test_and_Set


cf> : Data를 읽는것과 쓰는것을 하나의 instruction으로 처리할수 없기 때문에 동기화 문제가 발생한다.

 


 

* Synchronization Hardware


 

 


# 보라색 그림 설명

: a라는 데이터를 읽어내고, 그다음에 a라는 데이터 값을 1로 바꿔주는 것을 하나의 instruction으로 처리 해준다.


cf> 여기서 1은 lock = 1(true)를 의미 한다.


'cs > os' 카테고리의 다른 글

#6-4. Process Synchoronization  (0) 2018.01.22
#6-3. Process Synchronization  (0) 2018.01.21
#6-1. Process Synchronization  (0) 2018.01.11
#5-3. CPU SCHEDULING  (0) 2018.01.09
#5-2. CPU SCHEDULING  (1) 2018.01.08

#6-1. Process Synchronization
: os에서의 race condition 3가지의 예시와 해결방법에 대해 알아보도록 하자!

 

 

[INTRO]

* 데이터의 접근

 

 

 

# Execution Box : 연산하는곳
  Storage Box   : 데이터가 저장된곳

 

#데이터를 연산을하고 수정을하고 데이터를 저장하는 방식은 누가 먼저 읽어 갔느냐에 따라 결과가 달라질수도 있고, 그렇게 했을때 생기는 문제를 Synchronization 문제라고 하고, 이것을 해결할수 있는 방법을 여기서 공부한다.

 

* Race Condition (경쟁상태)

 

 

 

# count++ 와 count--가 동시에 접근할때 count에 문제가 생긴다. 이런 경우, Race Condition의 가능성이 있다.

# 이것을 조율해줘야 하는 방법이 필요하다!!! => Synchronization

 

 

# os에서 race condition은 언제 발생 하는가?

 

 

# user모드에서는 괜찮던게 os의 kernel에서는 여러 프로세스들이 공유하는 데이터들이 있기 때문에 문제가 생긴다. 이 예시들을 자세히 알아보자

 


* os에서의 race condition (1/3)
: kernel mode 수행중에 interrupt 처리가 들어왔을때.

 

 

 

 

# count++(1 증가 시키는 문장) :
1. load : 메모리에 있는 값을 cpu 안에있는 register로 불러 들이고,
2. Inc : 그 값을 1 증가 시키고,

3. Store : 그 다음에 레지스터 값을 다시 메모리에 저장.

 

# 그러나, 저 루틴 수행 과정중 interrupt가 들어왔을 경우에 저 작업을 잠시 멈추고 interrupt 처리 루틴으로 넘어가게 된다.

(Interrupt Handler : 근데 이게 kernel 코드이다.)

 

# 이렇게 되면 감소시킨 것을 반영이 안되고 증가하는 것만 반영이 되게 된다.

 

 

???) 어떻게 해결 하는가?
: disable, enable interrupt로 해결 한다!


저런 오류가 일어 나지 않게 count++가 시작되면 disable interrput가 시작되어 interrupt를 받아들이지 않는다.

 count++연산이 끈나면 enable interrupt가 시작되어 다시 interrupt를 받을수 있는 상태로 전환 된다.

 

 

* os에서의 race condition (2/3)
: 공유 공간인 kernel mode에서 cpu할당시간이 끈났을 때

 

 

 

 

# 본인의 코드만 실행하는것이 아니라 System call을 통해서 os에 서비스를 대신해 달라고 하는 경우가 있다. 그래서 프로그램은 user mode와 kernel mode를 번갈아 가면서 실행을 하게 된다.

 

 

# A라는 프로그램은 cpu를 독점적으로 쓰느게 아니라 할당시간이 있고, 할당시간이 끈나면 cpu를 반납하게 되어 있다.

 

# 이 그림에서는 A가 cpu를 쓰다가 할당시간이 끈나서 cpu가 B한테 넘어간 것 이다. 그래서 B가 cpu를 쓰다가 본인의 할당시간이 끈나서 다시 A한테 넘어오는 그림이다.

 

# 여기서 문제점은 user mode일때 cpu가 반환되면 상관없는데, system call로 이해 kernel mode로 들어간 후에 cpu사용권을 반납했다. A, B 모두 kernel mode라는 공유공간에서 count를 건드리는 작업을 하기 때문에 문제가 발생하게 된다.

 

# 이 경우에는 논리적으로는 +2가 증가해야 되는데 B의 +1은 반영이 되지 않게 되는 문제가 발생한다.

 

???) 어떻게 해결하고 있는가?
: 프로세스가 kernel mode에 있을때는 할당시간(time quantum)이 끈나도 cpu를 뺏기지 않도록 하고 있다.


 

* os에서의 race condition (3/3)
: cpu가 여러개 있는 환경.(즉, 작업 주체가 여러개 있는 상황)

 

 

 

???) 어떻게 해결 할까?
: 데이터에 lock 과 unlock을 걸어서 이중접근을 방지 시킨다.


 

* Process Synchronization 문제

 

 


* The Critical-Section Problem
cf> Critical-Section(임계구역) : 공유 데이터를 접근하는 코드(critical section은 코드임에 주의!!!)

 

 


 
# 다음시간에 이 문제를 해결하는 알고리즘을 알아보자!

'cs > os' 카테고리의 다른 글

#6-3. Process Synchronization  (0) 2018.01.21
#6-2. Process Synchronization  (0) 2018.01.15
#5-3. CPU SCHEDULING  (0) 2018.01.09
#5-2. CPU SCHEDULING  (1) 2018.01.08
#5. CPU SCHEDULING  (0) 2018.01.04

#5-3. CPU SCHEDULING


cf> 여태까지 스케줄링은 큐에서 한줄서기를 하면서 cpu사용을 기다려 왔지만,

      Multilevel queue와 Multilevel feedback queue는 여러줄 서기를 할 수 있다!!


* Multilevel Queue

 


# 밑에 그림을 통해 우선순위를 알수 있다.
: 맨 위에 줄이 우선순위가 높으며, 밑으로 갈수록 우선순위가 낮아진다.

 

 

 

# system process : 시스템과 관련된 일을 하는 프로세스
  interactive Process: 사람하고 관련된 일을 하는 프로세스
  interative editing process : 그것보다는 살짝 인터렉션이 떨어지는 프로세스
  batch process : cpu만 오랫동안 사용하는 프로세스를 여기서는 batch process라고 얘기를 하는것 같다.
  student process : 학생을 무시하는건가....?

=> 여기는 완전 계급제!
 즉, 맨 위에 부터 비어있나 확인을 해서 밑으로 내려간다. 밑에 있는 프로세스는 영원히 cpu할당을 못 받을 수 도 있다.(starvation 발생)

 

cf> 반면에!!
Multilevel Feedback Queue는 완전 계급제는 아니다. 방탕하게 살면 우선순위가 떨어지기도 하고 열심히 살면 우선순위가 올라가기도 한다!!

 (다음에 나오는 Multilevel Feedback Queue 그림 참고하기!!)

 

 

# 고려해야 할점?

 

 - Ready queue를 여러 개로 분할
  v. foreground (interactive)
  v. background (batch-no human interaction)

 

 - 각 큐는 독립적인!! 스케줄링 알고리즘을 가짐.
  v. foreground  => RR
  v. background  => FCFS

 # 줄에 특성에 맞는 queue별 스케줄링을 채택! (이렇게 채택된 이유를 알겠지?)

 

 - 큐에 대한 스케줄링이 필요
  v. Fixed priority scheduling
    # 이 방식은 우선순위를 아주 강하게 주어 우선순위만을 사용하는 방식인데, 이렇게 되면 우선순위가 낮은 프로세스들은 starvation이 발생한다. 이에대한 해결책이 Time slice!!

  v. Time slice


  - 각큐에 CPU TIME을 적절한 비율로 할당
     ex> 우선수위 높은 RR은 80%주고, 낮은 FCFS는 20%주고!


* Multilevel Feedback Queue

# (Multilevel queue와 비교하여)고려해야될 점
(사진의 빨간색 글씨 부분들!!! (중요!))

 

 

 

# 우선순위가 높으면 RR의 quantum을 짧게 해주며, 우선순위가 낮아질수록 quantum을 높여줘서 나중에는 FCFS가 되게끔 한다.

 

 

 

-----------------------------------------------------------------------------------------------------------------------
# 여기까지는 CPU가 하나일때의 CPU SCHEDULING 이었다면, 지금부터의 내용은
CPU가 여러개 일 경우,
Thread가 여러개일 경우,
등등 특이한 case의 cpu스케줄링을 알아 보겠습니다.


 

* Multiple-Processor Scheduling
: 이 부분은 화두만 보고 넘어가자!

 

 

 

# Load sharing : 하나의 줄에만 부하되는것을 막는 것.

# Symmetric Multiprocessing : cpu가 모두 대등한 것.

# Asymmetric Multiprocessing : 하나의 cpu가 컨트롤을 담당하고 나머지가 그 cpu를 따르는 것.

 

 

* Real-Time Scheduling
: 반드시 데드 라인을 보장해야 한다.

 

# 그때 그때 스케줄링하기보다는 real time job들이 정해져 있고, 그것들을 미리 스케줄링해서 데드라인이 보장되도록 적재적소에 배치되도록 하는 그런 시스템을 쓰고 있다.

 

cf> real time job : dead라인이 있는 job!
    (정해진 시간안에 완료해야하는 작업이 있는 job)

 

 

 

# hard는 데드라인이 꼭 지켜져야 하고
  soft는 데드라인을 지켜야하는 의무가 좀더 부드럽다.


* Thread Scheduling

cf> Thread : 프로세스 하나 안에 cpu 수행단위.

# User level Thread : 사용자 프로세스가 직접 쓰레드를 관리하고 os는 그 쓰레드를 모르는 상황. => 그래서 os가 프로세스에게 cpu사용권을 주면 그 프로세스 내에서 어떤 쓰레드에게 cpu사용권을 줄지를 결정하는 것. => "Local Scheduling"


# Kernel level Thread : os가 쓰레드의 존재를 이미 알고 있는 상황. => 그래서 kernel의 단기 스케줄러가 cpu사용권을 결정하는 것. => "Global Scheduling"

 

 

 

* 알고리즘 성능 평가

 

cf> trace : 실제 프로그램을 통해 추출한 input data.

 

 

 

 

'cs > os' 카테고리의 다른 글

#6-2. Process Synchronization  (0) 2018.01.15
#6-1. Process Synchronization  (0) 2018.01.11
#5-2. CPU SCHEDULING  (1) 2018.01.08
#5. CPU SCHEDULING  (0) 2018.01.04
#4. Process Management  (0) 2018.01.02

* 복습

cpu 스케줄링의 매커니즘 : ready 큐에 있는 프로세스중 누구한테 cpu를 줄지 정하는 것.
(크게 두가지 이슈가 있다)


1. cpu burst에 들어온 수많은 프로세스들중 누구한테 줄까?
2. cpu를 프로그램한테 줬으면 I/O를 하러 나갈때까지 계속 줄꺼냐? 아니면 중간에 뺏을꺼냐?

 

즉, 누구한테 줄것인가? 일단 줬으면 중간에 뺏어 오게 할 수 있게 할 것인가.
(공평도 필요하지만 효율적으로 하기위한 매커니즘)


* CPU 스케줄링 알고리즘

 

 

# 알고리즘들을 크게 두가지로 나누어 본다면,

 1) NONPreemtive 한 스케줄링 : 강제로 cpu를 빼앗지 않는 방법 (일단 cpu한번 주면 자진반납할때 까지 cpu보장해주는 방법- 비선점형)

 2) Preemtive 한 스케줄링 : 언제든지 뺏어올 수 있는 방법 (선점형, 요즘은 이걸 많이씀)

 

 

* CPU 스케줄링 성능 척도

 

 

 

# 성능척도를 크게 두가지로 생각해 볼수 있다.
 1) 시스템 입장에서의 성능 척도
  : CPU 하나를 가지고 최대한 일을 많이 시키면 좋은것(파란색 2개)
 2) 프로그램 입장에서의 성능 척도
  : 내가(프로세스) CPU를 빨리 얻어서 빨리 끈나면 좋은것, 그래서 시간과 관련이 있는 3가지를 고려(빨간색 3개)


# 척도 소개


 (처음 2개는 사장 입장)
 - CPU utilization : 전체 시간중에서 cpu가 놀지 않고 일한 시간.
 - Througput : 주어진 시간 동안에 몇개의 작업을 처리 하였느냐

 

 (밑에 3개는 고객입장(빨리 서비스 받고 싶다.))
 - Turnaround time : cpu를 쓰러 들어와서 다쓰고 나갈때 까지의 시간. (waiting time + cpu이용시간)
 - Waiting time : cpu를 쓰고자 ready큐에서 기다리는 시간
 - Response time : ready큐에 들어와서 cpu쓰겠다고 들어와서 처음으로 cpu를 얻기까지 걸린 시간.

 

cf> waiting time과 response time의 차이를 구분해보자면, preemtive(선점형)인 경우, cpu를 계속해서 돌려쓰게 되는데
1) waiting time : 기다리는거 모두 합한 값.
2) response time : 제일 처음 기다린 시간.
3) turnaround time : waiting time + 실행 시간

 

???) 시간을 왜 굳이 3개씩이나 나누지?
: 응답시간을 둔 이유는 time sharing 환경에서는 처음으로 cpu를 얻는 시간이 사용자 응답과 관련해서 굉장히 중요한 시간의 개념이다. 그래서 반환시간도 있고 대기시간도 있지만 응답시간을 별도로 둬서 이야기 하는 이유이다!


* FCFS
 : 먼저오면 먼저 처리 (NoonPreemtive)

 

 

 

# NoonPreemtive한 스케줄링이다. 중간에 시간이 많이 걸리는게 있다면 비효율적이다.

 

 

 

# 앞에 경우와 비교해보면 평균 waiting time이 짧아진것을 볼 수 있다.

# Convoy effect : 긴 프로세스가 먼저 도착해서 짧은 프로세스들이 지나치게 많은 시간을 기다리는 효과를 의미. (부정적 효과)

 

 

SJF
 : 수행시간이 짧은게 먼저 처리

 

 

 

# Average waiting time이 최소화 되는 방법.

 

# SJF 알고리즘도 두가지 방법으로 나누어서 생각해 볼수 있다.

1) NoonPreemtive 한 방법
2) Preemtive한 방법 : cpu를 줬다 하더라고 남은 수행시간이 더 짧은 애가 오면 cpu를 빼앗긴다.(SRTF 라고도 부른다)

 

 

# 두가지 예를 봐보자

 

1) NoonPreemtive version.


 

 


2) Preemtive version.


 

 

 

# Preemtive 버전이 더 짧다는것을 알수 있다. (더 좋다.)

 

 

???) 그러나 두가지 문제점이 있다.

 

1) starvation(기아현상) : SJF는 수행시간이 짧은거를 선호 하기 때문에, 수행시간이 긴 프로세스는 영원히 서비스를 못 받을 수도 있다.

2) 매번 cpu사용 시간을 미리 알수 없다는게 문제이다. 그럼 SJF는 실제로 적용 못하나요? => 정확히는 알수 없지만, 과거의 사례(과거의 CPU burst time)을 통해서 추정한다

 

 

 

# 다음 cpu burst time 예측

 : 점화식을 해석해 보면 과거일수록 반영하는 가중치가 줄어든다.

 

 

 

 

 

 

 

 

 

* Priority Scheduling 
 : 우선순위가 높은 프로세스한테 cpu할당

 

 

 

# Priority Scheduling 알고리즘도 두가지 방법으로 나누어서 생각해 볼수 있다.

1) NoonPreemtive 한 방법
2) Preemtive한 방법 : cpu를 줬다 하더라고 남은 수행시간이 더 짧은 애가 오면 cpu를 빼앗긴다.(SRTF 라고도 부른다)

cf> 작은 숫자가 우선순위가 높다.

 

# Aging : 아무리 우선순위가 낮더라 하더라도, 시간이 지나게 되면서 우선순위를 조금씩 높여주자(starvation의 해결책!)

 

* Round Robin
: 가장 현대적인 스케줄링 알고리즘, 여태 우리가 배웠던 시스템이 RR이다.

 

 

 

# RR의 장점 : cpu 응답시간이 빨라진다. (누구든지 조금만 기다리면 cpu를 맛볼수 있다.)
(n-1)q 만 기다리면 내 차례가 돌아온다. (q라는 퀀텀을 짧게 잡아줄수록 내 차례가 빨리 다가온다.)

 

#
1) q를 너무 크게 잡으면 : FCFS
2) q를 너무 짧게 잡으면 : context switch 오버헤드가 커진다.(시스템 전체 성능이 나빠질수 있다.)
 => 즉, 너무 크거나 짧게 q를 잡으면 성능이 나빠진다.

 

 

# 할당 시간(q)이 20 인경우의 예제

 

 

 

# RR의 장점 : Response time이 줄어든다!!

'cs > os' 카테고리의 다른 글

#6-1. Process Synchronization  (0) 2018.01.11
#5-3. CPU SCHEDULING  (0) 2018.01.09
#5. CPU SCHEDULING  (0) 2018.01.04
#4. Process Management  (0) 2018.01.02
#3-3. Thread  (0) 2017.12.29

#5 CPU SCHEDULING

 


 

* cpu and I/O Bursts in Program Execution




# cpu bursts : cpu만 실행 되는곳

  I/o bursts : I/O만 실행 되는곳


# 프로그램의 종류에 따라 cpu burts와 I/O bursts의 빈도가 달라진다.

cf> 주로 사람이 만지는 프로그램은 I/O bursts가 높아지고,

    과학 계산용 프로그램은 cpu bursts가 높다.


* cpu-bursts time의 분포

 

 


# 그래프 분석 : job의 종류가 섞여있다.

# cpu bursts가 짧은 경우(빨간색 네모) : 중간에 i/o가 많이 끼어드는 경우가 많았다. => I/O bound job

  cpu bursts가 긴 경우(파란색 네모)   : 중간에 i/o가 많이 끼어들지 않았다. => cpu bound job


!!!) 이렇듯 여러 종류의 job(=process)이 섞여 있기 때문에 cpu 스케줄링이 필요하다.

 

  - cpu 스케줄링의 중요한 역할 중에 하나는!!!

  : I/O bound job 처럼 사람하고 interaction 하는 job 에게 cpu를 우선적으로 주는것. (효율성을 위해!!)

    즉, interactive 한 job들을 오래 기다리게 하지 않는것


* 프로세스의 특성 분류

 

 


* CPU Scheduler & Dispatcher

 

 


# CPU 스케줄러 : 누구한테 CPU를 줄지를 정함.

 ???) CPU 스케줄러는 HW or SW?

     : CPU 스케줄러는 os kernel에 있는 스케줄링 해주는 code이다.


# Dispatcher : cpu를 누구한테 줄지 결정했으면, 그 친구에게 cpu를 넘겨주는 역할을 함.

  cf> 마찬가지로 kernel에 있는 code.


!!!과정))

 - 방금전에 cpu에서 돌아가던 process의 context를 save하고, 

 - 새로 cpu를 넘겨주는 process의 context를 펼쳐놓는다.

 - cpu 안에다가 register 값 세팅 해놓고,

 - 그런다음에 cpu를 넘겨준다.


# cpu 스케줄링이 필요한 경우 

 1. I/O 작업처럼 오래 걸리는 작업을 하는 경우

 2. cpu를 계속 쓰고 싶은데 timer interrupt가 발생해서 빼앗는 경우

 3. 오래 걸리는 작업이 끈낫을때 (device controller가 interrupt를 걸어서 ready상태로 만들어 줌.)

 4. 

'cs > os' 카테고리의 다른 글

#5-3. CPU SCHEDULING  (0) 2018.01.09
#5-2. CPU SCHEDULING  (1) 2018.01.08
#4. Process Management  (0) 2018.01.02
#3-3. Thread  (0) 2017.12.29
#3-2. Process  (0) 2017.12.27

#4. Process Management

 

 

* 프로세스의 생성
: 부모 프로세스가 자식 프로세스를 생성.
 cf> 생성하는 방법 : 복제 생성(메모리(code, data, stack), cpu문맥(pc)을 copy.)

 

 v. 계층구조 : 트리구조

 v. 프로세스는 자원을 필요함(실행이 되려면)
  - os로부터 받는다.
  - 부모와 자원을 공유한다.
   (공유하지 않는 모델도 있고, 일부만 공유하는 모델도 있다.)

 
  #보통 일반적인 경우는 자원을 공유하지 않고, 자식 프로세스가 생성되자마자 서로 cpu를 더 차지 하기 위한 경쟁관계가 된다.

 

 v. 수행(Excution)
  - 부모와 자식은 공존하며 수행되는 모델
  - 자식이 종료(terminate)될 때까지 부모가 기다리는(wait)모델

 

  # 부모와 자식이 공존하며 수행되는 모델이 있고, 자식을 생성하고 종료 될때까지 기다리는 모델이 두가지가 있다. 이 것들을 자세히 알아보자.

  # 메모리를 아끼기 위해 공유할수 있는거는 copy하지 않고 공유하는 효율적인것들도 있다.

 

 vv. 주소공간(address space)
  - 자식은 부모의 공간을 복사함(복제 생성)-------1단계(fork)
  - 자식은 그 공간에 새로운 프로그램을 올림------2단계(exec)

 

 vv. 유닉스의 예
  - fork() 시스템 콜이 새로운 프로세스 생성
   .부모를 그대로 복사 (os data except PID + binary)
   .주소 공간 할당

 

  - fork 다음에 이어지는 exec() 시스템 콜을 통해 새로운 프로그램을 메모리에 올림.

 

# 일단 fork()로 생성한다음에 복제해서 exec()를 사용해서 필요한거만 덮어 씌운다.

 

* 프로세스 종료

 v. 프로세스가 마지막 명령을 수행한 후 os에게 이를 알려줌(exit)
  - 자식이 부모에게 output data를 보냄(via wait).
    # 자식이 항상 부모보다 먼저 죽는다!!


  - 프로세스의 각종 자원들이 os에게 반납됨

# 자발적으로 프로세스가 종료되는것 : exit
    비 자발적으로 종료 되는것        : abort

 

 v. 부모 프로세스가 자식의 수행을 종료시킴(abort)
  - 자식이 할당 자원의 한계치를 넘어섬
  - 자식에게 할당된 task가 더 이상 필요하지 않음
  - 부모가 종료(wait)하는 경우
   . os는 부모 프로세스가 종요하는 경우 자식이 더 이상 수행되도록 두지 않는다.
   . 단계적인 종료

 

# 자식이 사치(자원한계치 이상)부리거나,

(일시키려고 자식을 생성했기 때문)할 일이 없거나,

 부모가 먼저 죽게 되는

경우에 자식을 죽인다.

 

 

* fork() 시스템 콜

 

 


# fork를 사용해서 프로세스를 만드는 코드
# fork() 빨간 부분은 시스템콜 부분이다.

 

# 문제점 : fork를 통해 복제를 할 경우 문제점
1) 복제를 해놨더니 지가 원본이라고 주장한다. 부모 프로세스를 자식 취급을 하면, 굉장히 혼란스러운 상황이 발생.
2) 부모와 똑같은 제어흐름을 따라가야 될거 같다....

해결책)) 
 1.부모와 자식을 구분을 해준다.
   어떻게?)) return value를 다르게 한다.
             자식은 0, 부모는 양수가 된다. (pid 설명.)

 2. 부모와 자식 프로세스가 다른일을 하게 해주는 system call
   : exec()

 

* exec() 시스템 콜
 : 어떤 프로그램을 완전히 새로운 프로세스로 태어나게 해주는 역할을 한다.


 

 

 

# execlp는 일종의 함수인데, 이것이 exec 시스템콜을 하게 된다.
# exec을 하게되면 fork와 달리 main 처음부터 실행을 하게 된다.

 

 

* wait()
 : 자식이 종료될때까지 기다리는 시스템 콜

 

 


ex> 리눅스 커널도 wait() 시스템콜이 사용된다. (콘솔 기다리는 거 상상하자.)


* exit()
 : 프로그램을 종료할때 실행하는 시스템 콜.

 

 

 

# 보통 자발적으로 종료될때 실행이 된다, 코드가 없어도(code에 exit()가 없어도) 마지막 코드 읽어주고 exit()가 실행됨.


* 프로세스와 관련한 시스템 콜(정리)

 

 - fork() : 부모 프로세스 복제 생성하는 것.
 - exec() : 완전히 새로운 프로그램으로 덮어 씌우는 것
 - wait() : 자식이 종료될때 까지 기다리는 것
 - exit() : 모든 자원을 반납하고 부모 프로세스한테 죽는다고 알리는 것.

 

 


* 프로세스 간 협력

 

 

 

# 프로세스는 원칙적으로 독립적이다.(부모가 자식을 죽이는것 말고는 프로세스들이 서롤 영향을 미치지 못한다.)

# process 협력: 프로세스간의 정보 교환
  정보를 교환하는 방법 => IPC

 

 

* Message Passing
 : 커널을 통해서 메시지를 passing 할수 있다.

 

# 메세지 패싱에는 또 2가지 방법이 있다.
: 상대 메시지를 받아볼 프로세스 이름을 명시 하느냐 안하느냐에 따라 2가지로 나뉨. (직접 통신 / 간접 통신)


# 2가지 방법으로 나누지만, 어쨋껀 메세지를 전달하려면 os의 kernel을 통해 전달해야 하는건 똑같다.

why?)) 프로세스 끼리는 메세지를 전달하는게 불가능 하기 때문에! 


# 간접 메시지는 아무나 꺼내갈수 있게 할수 있다! (상황에 따라 맞게 설계하도록 하자.)

 

 

* 일부 주소 공간을 공유하는 IPC
 : 아래 그림은 물리적인 공간

 

 

# 원칙적으로 process들은 독자적인 주소공간을 각자 가지고 있지만 일부 process들은 주소 공간을 공유한다.

# 공유된 주소공간은 접근을 바로 할 수 있다.

# shared 공간을 쓰려면 kernel한테 mapping(인제 shared 공간을 사용하겠다)을 해놓고, 그때부터는 사용자 프로세스끼리는 한쪽에서 쓰면 다른쪽에서 볼수있다.
 즉, shared memory 처음 하는것은 kernel의 도움을 받지만, 일단 kernel이 한번 해주면 그 이후는 가능하다. 
 
** 단, shared memory를 쓰려면 두 프로세스는 굉장히 신뢰할만한 프로세스여야 한다.

cf> 쓰레드들간의 협력은 주소공간을 같이 쓰기 때문에 유용하다.

 

 

 

'cs > os' 카테고리의 다른 글

#5-2. CPU SCHEDULING  (1) 2018.01.08
#5. CPU SCHEDULING  (0) 2018.01.04
#3-3. Thread  (0) 2017.12.29
#3-2. Process  (0) 2017.12.27
#3-1. Process  (0) 2017.12.27

#3-3. Thread

 


* PCB


 

 

# 프로세스마다 하나의 pcb가 만들어져서 os가 관리 하게 된다.

# 쓰레드는 프로세스 마다 가지고 있는 정보 중에서, cpu수행과 관련있는 정보만 가지고 있게 된다. => pc, register

 

 

** 쓰레드가 별도로 가지고 있는 정보들과 공유하는것들을 사진으로 알아보도록 하자.

 

 

 

 

# 쓰레드는 주소공간에서 data, code는 공유하고 stack 부분만 별도로 가지고 있게 된다.
# 쓰레드는 pcb에서 pc, register 정보만 별도록 가지고 있게 된다.

 

 

* Single and Multithread Process

 

 

#공유된 파란색 부분과 독자적으로 가지는 빨간색 부분!

 

 

* 쓰레드의 장점!!


--- cpu가 1개 일때도 얻는 장점! ---

 

1. 응답성(빠르다)

 

# 예)) 내가 웹브라우저를 띄워 놓고 어떤 포털사이드의 홈페이지 주소를 치게 되면 제일먼저 html 문서가 날라오게 된다.

그 문서를 web browser 화면에 display 하려고 봤더니 그 안에는 여러가지 이미지가 있다. 그거를 웹 브라우저가 해석을 해서 이미지들을 다시 웹서버에 요청을 한다. 그래서 그 이미지들이 도착을 하면 여러 다른 텍스트들도 집어 넣고 중간중간 이미지도 넣어가지고 하나의 웹 페이지를 완성해서 사용자에게 보여주게 된다.
 근데 그러한 과정에서 제일 먼저 html 문서를 읽어온 다음에 그 안에 있는 이미지들을 다시 웹서버에게 요청을 한다. 그러면 그게 오래 걸리는 작업이기 때문에 프로세스를 block 시킨다. 그럼 사용자 입장에서는 답답하다. 왜나하면 프로세스가 block 이 되어서 화면에 띄우는 걸 못한다.

이렇게 하지않고 웹 브라우저를 여러개의 쓰레드를 사용해서 만들게 되면 하나의 쓰레드만 block되고 다른 쓰레드가 일을 하게 된다. 그래서 더 빨리 결과를 볼 수 있게 된다.

 

-> 일종의 비동기식 입출력이 된다.

 

2. 자원 공유 (Resource Sharing)

 

# 하나의 프로세스를 만들고 그 안에 cpu 수행 단위만 여러개를 두게 되면, code, data 각종 자원은 쓰레드들이 공유 하기때문에 자원을 효율적으로 쓸수 있게 된다.

 

3. 경제성 (응답성과는 약간 다른 '빠르다'의 의미)

 

# 프로세스 내부에서 쓰레드 간의 cpu 스위칭이 일어나는 것은 굉장히 간단하다.

why)) 동일한 주소공간을 사용하기 때문에

<비교 : 문맥교환은 오버헤드가 크다.>
=> 같은일을 하는 작업이라면 프로세스를 여러개 만드는것보다 프로세스 안에 쓰레드를 여러개 두는것이 효율적이다.

 

--- cpu가 여러개 일때 얻는 장점! ---

 

4. 병렬성

 

# 프로세스는 하나지만 쓰레드가 여러개 있다면, 각각의 쓰레드들이 cpu를 점유해서 연산속도가 올라간다.
 => 결과를 더 빨리 얻을 수 있다. (멀티 프로세서 환경에서 효울적)

 

 

* 쓰레드 구현 방법

 

1. 커널 쓰레드 : 쓰레드가 여러개 있다는 사실을 운영체제 커널이 알고 있다. 그래서 하나의 쓰레드에서 다른 쓰레드로 cpu가 넘어가는것도 커널이 cpu 스케줄링 하듯이 넘겨주게 된다.

 

2. 유저 쓰레드 : 라이브러리르 통해서 지원된다. 프로세스 안에 여러 쓰레드가 있다는것은 os는 모르고 유저 프로그램이 관리 하는것.

 

# 커널의 지원을 받으면 커널 쓰레드.
  사용자 수준에서 쓰레드를 구현하게 되면 유저 레벨 쓰레드

 

3. real- time 쓰레드

 

 

'cs > os' 카테고리의 다른 글

#5. CPU SCHEDULING  (0) 2018.01.04
#4. Process Management  (0) 2018.01.02
#3-2. Process  (0) 2017.12.27
#3-1. Process  (0) 2017.12.27
#2-2. System Structure & Program Execution  (0) 2017.12.25

+ Recent posts