Semaphore 를 이용한 상호 배제의 문제를 생산사 - 소비자(한계 버퍼) 문제에 적용하여 baci 툴을 이용하여 구현을 한 것이다.

목표 및 내용

수업 시간에 배웠던 semaphore를 이용 상호 배제가 되도록 구현을 하는것 입니다. 우선 semaphore는 이 때 까지 의 busy waiting 이 계속 해서 cpu의 자원을 사용 하는 문제를 해결하기위하여 다른 프로세스가 임계 구역을 사용하고 있을 때, 진입을 하게 되면 블록 상태가 되고, 이미 임계구역에 들어가 있던 프로세스는 임계구역을 탈출 하면서, 신호를 보내주어 블록 되어있던 프로세스를 깨웁니다. 이러한 방법으로 cpu자원의 낭비도 없애고 상호배제 도 가능하게 할 수 있습니다.

semaphore wait signal 구조

 

2진 세마포어

 

세마포어 연산의 정의

알고리즘

소스코드

const int N = 10; // 버퍼의 공간을 잡을 상수

const int TRUE = 1; // TRUE = 1을 나타내는 상수

const int FALSE = 0; // FALSE = 0을 나타내는 상수, 세마포어에서 쓰이지는 않음.

semaphore mutex = 1; //이진 세마포어 를 구현하기위한 세마포어 변수 초기 값을 1로 설정

semaphore empty = N; //빈공간이 얼마만큼 남았는지 계산하는 세마포어 변수 초기 값을 버퍼의 갯수 만큼 설정.

semaphore full = 0; //생산품이 얼마만큼 차있는지 계산하는 세마포어 변수 초기값을 0으로 설정.

int buffer[N]; // 임계구역 공용 변수

void producer(void) // 생산자

{

int item = 1; //생산자가 1이라는 item을 생성함.

int i = 0; //공용번수의 자리번호를 정하기 위함.

int Num; //공용변수 배열에 값을 지정하기 위함. 10까지 지나면 다시 1로 돌아오기 때문에 % //연산을 해야 함.

while(TRUE) //무한 생산

{

wait(empty); //먼저 빈 공간을 할당 받고, 빈공간이 남아있다면 블록 되지않고 통과함

// cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl<<endl;

wait(mutex); //2진 세마포어로 임계구역을 쓰는 프로세스가 있는지를 확인.

//초기값이 1이므로 다른 프로세스가 먼저 사용하지 않았다면 0으로 만들고 진입.

cout<<"Insert item "<<i<<" buffer place"<<endl; //임계구역에 들어왔음을 출력.

cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl; //세마포어 번호

Num = i%N; //나누기 연산자를 쓴 것은 9 다음 카운트로 10이아닌 0으로 돌아가게 하기위 //함. 앞에 test_and_set구현의 이웃 프로세스에게 자리 양보 의 응용.

// if(buffer[Num] == 0)

// {

buffer[Num] = item; // 공용변수에 생산품을 집어넣음

i = (i+1)%N; // 공용변수의 다음 자리로 이동

cout<<"buffer["<<Num<<"] 's insert_item is "<<buffer[Num]<<endl<<endl;

// }

// else

// {

// cout<<"buffer["<<Num<<"] is not empty"<<endl;

// }

//여기서 if else 문을 썼던 것은 %연산자로 인해 환형 큐 형식으로 되어서 만약 공용번수에 모든 값을 집어 넣고

//나서도 또 넣으려고 시도 할 때 예외처리 하려고 했었으나, 이렇게 하지 않아도 empty 와 full 세마포어 로 인해

//블록이 되므로 굳이 쓰지 않아도 됩니다.

signal(mutex); //임계구역을 빠져나감을 알림 mutex값을 +1 증가 시켜주고 신호를 보냄.

// cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl<<endl;

signal(full); //full 값을 증가시켜줌으로 소비자가 임계구역이 비어있지 않다는것을 알림.

}

}

void consumer(void) //소비자

{

int item = 0; //소비자가 소비를 하고나면 원래 초기 빈값을 넣어줌

int i = 0; //공용번수의 자리번호를 정하기 위함.

int Num; // 역시 % 연산자로 인해 연산을 하여 값을 넣어야 하므로 변수를 생성함.

while(TRUE) //무한 소비

{

wait(full); //full 세마포어 변수가 0일시 공용변수가 비어있으므로 소비 할 수 없고 블록 됨.

// cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl<<endl;

wait(mutex); //2진 세마포어로 임계구역을 쓰는 프로세스가 있는지를 확인.

cout<<"Remove item "<<i<<" buffer place"<<endl; //임계구역 진입을 출력함

cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl; //세마포어 번호

Num = i%N; // 위의 생산자에서의 설명과 같이 9 -> 0으로 돌리기 위해 %연산을 함.

// if(buffer[Num] == 1)

// {

buffer[Num] = item; // 소비자가 소비 후 버퍼를 빈상태로 돌림.

i = (i+1)%N; //공용변수의 다음 자리로 이동.

cout<<"buffer["<<Num<<"] 's item remove result is "<<buffer[Num]<<endl<<endl;

// }

// else

// {

// cout<<"No product in"<<"buffer["<<Num<<"]"<<endl;

// }

//여기서 if else문을 썼던겄도 위에 생산자에서의 이유와 동일함.

signal(mutex); //임계구역을 빠져 나감을 알림.

// cout<<"Mutex : "<<mutex<<" Empty : "<<empty<<" Full : "<<full<<endl<<endl;

signal(empty); // 하나를 소비했으므로 빈공간이 한개 더 늘었음을 알려줌.

}

}

void prod(void) //생산자 스레드

{

producer();

}

void consum(void) // 소비자 스레드

{

consumer();

}

void main()

{

int i;

for(i=0; i<N; i=i+1) // 공용변수의 초기화

{

buffer[i] = 0;

}

cobegin // 병행 수행을 하기위한 cobegin문.

{

prod();

consum();

}

}

실행결과 화면

 

 

'Study > OS' 카테고리의 다른 글

Monitor 를 이용한 생산자-소비자 구현  (0) 2012.05.04
Test-And-Set  (0) 2012.04.27
Bakery 알고리즘  (1) 2012.04.22
Peterson 알고리즘  (0) 2012.04.22
jBACI 사용법  (0) 2012.04.15

+ Recent posts