CS/OS

[운영체제] 6-1. Testset Instruciton

F12:) 2023. 10. 10. 16:05

이번 글에서는 critical section problem을 해결하는 방법 중에서 testset을 이용한 방법을 다뤄보겠습니다.

 


하드웨어의 도움으로 critical seciton problem을 해결하기 위해 우리는 atomic operation을 활용할 것입니다.

그런데 뭔가 이상하지 않나요?? 우리가 이전 글에서 SW Solution으로 해결하기 위해 critical section을 atomic operation으로 정의해서 진행했더니, critical section을 진행하는 도중에는 interrupt를 받을 수 없으므로 옳지 못하다고 다뤘으니까요.

 

그래서 여기서는 하드웨어의 지원을 받아서, critical section이 아닌 entry section과 exit section을 atomic operation으로 만들어줍니다.

 

조금 더 자세히 알아봅시다.

 

 

Test and Set Instruction

좀 전에, critical section problem을 해결하기 위해 entry section과 exit section을 atomic하게 만든다고 했습니다. 그를 위해 이용하는 것이 testset()이죠.

 

testset의 코드를 확인해봅시다.

boolean testset(int i){
	if(i==0){
    	i = 1;
        return true; 
    }
    else{
    	return false;
    }
}

testset은 이런 식으로 구성되어 있으며, 각 행에서 의미하는 바는 다음과 같습니다.

 

만약 i==0이라면, critical section을 수행 중인 프로세스가 없음을 의미합니다. 따라서, i=1로 만들어, critical section을 수행하고 있다는 것을 나타내고 true를 return합니다.

 

만약 i==1이라면, 누군가가 critical section을 수행하고 있다는 것을 의미하므로 false를 반환하게 됩니다.

 

이러한 testset()의 메서드를 atomic하게 만듦으로써 critical section problem을 해결할 수 있는 것이죠. 이를 적용한 코드를 확인해봅시다.

 

int n = 10; // 프로세스의 개수
int bolt;	// critical section이 수행 중인지 확인하는 변수

void P(int i){
	while(true){
    	while(!testset(bolt)); // entry section
        /* critical section */
        bolt = 0;   // exit sectoin
    }
}

main(){
	bolt = 0;
    parbegin(P(1), P(2), ... , P(n));
}

main부터 살펴보시죠. parbegin은 인자로 들어가있는 프로세스들을 생성하고 수행하는 것을 의미합니다.

 

bolt를 통해서 각 프로세스들은 critical section이 수행 중인지 확인합니다. 만약 누군가 critical section을 수행한다면, while(!test(bolt))를 계속해서 busy waiting하게 됩니다.

 

만약 critical section을 수행하는 프로세스가 없다면, while문을 거치지 않고 critical section을 수행하게 되죠. critical section을 마쳤다면, bolt = 0;으로 만들어서 다른 프로세스가 critical section을 수행할 수 있도록 해줍니다.

 

 

한가지 명심해야할 것은, 우리는 atomic operation을 testset()으로 사용합니다. 즉, critical section이 atomic operation이 아니므로, process switch가 일어날 수 있습니다. 이것이 SW Solution과의 차이인 것이죠.

 

 

Advantages

우리가 이러한 방식으로 critical section problem을 해결하면 어떤 이점이 있을까요??

  • 몇 개의 프로세스든지 적용가능합니다.
  • 간단하여, 쉽게 작동합니다.
  • 여러 프로세스들간의 critical section problem을 해결할 수 있게 됩니다.

 

 

Disadvantages

하지만 이러한 방식은 우리가 전에 언급한 critical section problem의 모든 문제를 해결해주지는 않습니다.

 

Busy Waiting

우선 이 방식은 busy waiting을 사용합니다. 따라서, 프로세스가 critical section problem을 수행할 수 없을 때, 자신의 time slice가 다 끝날 때까지 계속 프로세서를 가지고 있게 되는 것입니다.

 

> 하지만 busy waiting이 무조건적으로 잘못된 것은 아닙니다. 간혹, busy waiting이 필요할 때가 있으므로 요즘에도 testset 방식으로 critical section problem을 해결하기도 합니다.

 

Bounded Waiting

이전 글에서 최악의 경우일 떄의 bounded waiting을 지원하지 않습니다. 

 

> 하지만, bounded waiting을 지원하지 않는 경우는 '최악'의 경우입니다. 요즘 추세로는 이러한 일이 거의 발생할 수 없다고 간주하고 최악의 경우를 무시합니다.

 

Dead Lock

Dead Lock 문제 또한 이 글에서 언급하였습니다. 개념에 대한 설명은 생략하고 왜 이러한 경우가 발생하는지 확인해봅시다.

 

정확히 이 Dead Lock 문제는 testset() 때문에 발생한다고 할 수 있습니다. 또한 프로세스들간의 우선순위가 존재할 때 발생할 수 있게 됩니다.

 

그에 대한 예시를 설명해보겠습니다.

 

'''

P1 프로세스가 critical section을 수행 중이라고 해봅시다. critical section을 수행하다가 P2 프로세스가 생성되어 ready 상태가 됩니다. P1보다 우선순위가 높은 P2는 P1의 자원을 빼앗고, P2가 프로세서를 할당받습니다. 이제 P2가 P1과 동일한 critical section을 수행해야합니다. 그래서 entry section으로 들어가지만, 이미 P1이 bolt = 1로 만들었고, 그 상태에서 ready 상태가 되었으므로 P2는 critical section을 수행하지 못합니다. 이러한 문제가 해결되지 않고 계속 P2는 critical section을 수행하기를 기다리고, P1은 자원을 할당받지 못해 critical section을 완수하지 않아 Dead Lock 문제가 발생하게 되는 것입니다.

'''

 

이러한 문제는 요즘 시대에 해결하도록 처리되었습니다. 가령, P1이 너무 오래 critical section내에 있지만 ready 상태일 때, P1에세 프로세서를 배정해준다던지.. 하는 방식으로 말이죠.

 


하지만 이러한 disadvantage가 분명 존재하고, 이를 해결하기 위해 더 좋은 개념인 semaphore가 나오게 됩니다. 다음 글에서는 semaphore에 대해서 다룹니다.