📚생산자-소비자 문제

📄생산자-소비자 문제 정의

생산자-소비자 문제는 두 협력 프로세스 사이에 버퍼를 두고, 한쪽 프로세스는 데이터를 넣고 다른 쪽 프로세스는 데이터를 꺼내는 상황을 다루는 문제이다.

  • 생산자-소비자 문제 조건
    1. 버퍼에 여러 프로세스가 동시에 접근 할 수 없음.
    2. 버퍼의 크기가 유한하다.

두 번째 조건 때문에 생산자-소비자 문제를 유한 버퍼 문제라고도 한다.

첫 번째 조건은 생산자-소비자 문제를 해결하기 위해 상호배제가 필요하다는 것을 의미한다. 두 번째 조건은 생산자-소비자 문제를 해결하기 위해 동기화가 필요하다는 것을 의미한다.


📄세마포어를 이용한 해결

생산자-소비자 문제는 세마포어를 이용하여 해결할 수 있다. 아래는 세마포어 mutex, empty, full을 이용한 생산자와 소비자의 수도코드이다. mutex의 초기값은 1, empty의 초기값은 버퍼의 크기 n, full의 초기값은 0으로 한다.

상호배제를 위해 세마포어 mutex를 이용한다. 생산자가 버퍼에 데이터를 넣는 부분과 소비자가 버퍼에서 데이터를 꺼내는 부분은 동시에 수행될 수 없으므로 임계영역이 되며, 임계영역 앞에 P(mutex)를 두고 임계영역 뒤에 V(mutex)를 둬서 생호배제를 해결한다.

버퍼가 가득 찬 경우 동기화를 위해 세마포어 empty를 이용한다.

버퍼가 빈 경우 동기화를 위해 세마포어 full을 이용한다. full은 버퍼에 존재하는 데이터 개수이고 초기값은 0, 버퍼가 가득 찬 경우에는 n이 된다.

empty = n, full = 0인 경우에 소비자는 P(full)을 이용하여 버퍼에 진입하지 못하고 대기하게 된다.생산자는 P(empty)를 이용하여 버퍼에 진입이 가능하고, 버퍼에 데이터를 넣은 다음에 V(full)을 이용하여 소비자가 버퍼에 진입할 수 있도록 깨운다. 대기 중인 소비자가 없다면 full을 1 증가시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 생산자
while(true)
{
  데이터 생산
  P(empty);
  P(mutex);
  버퍼에 데이터 넣음
  V(mutex);
  V(full);
}

// 소비자
while(true)
{
  P(full);
  P(mutex);
  버퍼에서 데이터 꺼냄
  V(mutex);
  V(empty);
  데이터 소비
}



📚판독기-기록기 문제

📄판독기-기록기 문제 정의

판독기-기록기 문제는 여러 협력 프로세스가 파일 같은 공유자원을 사이에 두고 데이터를 쓰거나 읽는 상황을 다루는 문제이다.

  • 판독기-기록기 문제 조건
    1. 하나의 기록기가 공유 자원에 데이터를 쓰는 중에는 다른 기록기나 판독기는 공유자원에 접근할 수 없다.
    2. 여러 판독기는 동시에 공유자원에서 데이터를 읽을 수 있다.

첫 번째 조건은 판독기-기록기 문제를 해결하기 위해 상호배제가 필요하다는 것을 의미한다. 두 번째 조건은 판독기가 공유자원에서 데이터를 읽는 동안 다른 판독기는 공유자원에 접근 가능하기에 추가적인 고려사항이 발생한다.


  1. 제1판독기-기록기 문제
    제1판독기-기록기 문제는 판독기가 공유자원에 접근 중이라면 기록기보다 판독기에 우선순위를 주는 것이다. 기록기에 상관없이 새로운 판독기는 즉시 공유자원에 접근할 수 있다는 의미이다. 판독기-기록기 문제의 두 번째 조건을 충실히 따르지만 기록기가 기아상태에 빠질 수 있다는 단점이 있다.

  2. 제2판독기-기록기 문제
    제2판독기-기록기 문제는 판독기가 공유자원에 접근 중이라면 판독기보다 기록기에 우선순위를 주는 것이다. 대기 중인 기록기가 있으면 새로운 판독기는 공유자원에 접근할 수 없다는 의미이다. 이는 기록기가 기아상태에 빠지는 것을 방지하지만 판독기의 병행성이 떨어질 수 있다. 또한 기록기에 우선순위를 주는 방식에 따라 판독기가 기아상태에 빠질 수도 있다.



📄세마포어를 이용한 해결

제1판독기-기록기 문제는 세마포어를 이용하여 해결 가능하다. 2개의 세마포어 wrt와 mutex를 이용하고 두 세마포어 초기값은 모두 1로 둔다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 기록기

P(wrt);
공유자원에 쓰기
V(wrt);


// 판독기

P(mutex);
rcount = rcount + 1;
if(rcount == 1) then P(wrt);
V(mutex);
공유자원에서 읽기
P(mutex);
rcount = rcount - 1;
if(rcount == 0) then V(wrt);
V(mutex);


제2판독기-기록기 문제 또한 세마포어를 이용하여 해결 가능하다. 5개의 세마포어 wrt와 mutex를 이용하고 rd, wrt, mutex1, mutex2, mutex3의 초기값은 모두 1로 둔다. 일반 변수 rcount와 wcount의 초기값은 0이다. 기록기가 대기 중일 때 새로운 판독기가 들어오면 임계영역을 수행하지 못하도록 rd가 제1판독기-기록기 코드에 추가되었다. 기록기에 우선순위를 주기 위해 mutex3도 추가되었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 기록기

P(mutex2);
wcount = wcount + 1;
if(wcount == 1) then P(rd);
V(mutex2);
P(wrt);
공유자원에 쓰기
V(wrt);
P(mutex2);
wcount = wcount - 1;
if(wcount == 0) then V(rd);
V(mutex2);


// 판독기

P(mutex3);
P(rd);
P(mutex1);
rcount = rcount + 1;
if(rcount == 1) then P(wrt);
V(mutex1);
V(rd);
V(mutex3);
공유자원에서 읽기
P(mutex1);
rcount = rcount - 1;
if(rcount == 0) then V(wrt);
V(mutex1);



📚프로세스 간 통신

📄공유 메모리 방법

공유 메모리 방법은 협력 프로세스가 동일한 변수를 사용하여 데이터를 서로 공유하는 방법이다. 변수가 사용하는 메모리 공간은 협력 프로세스들이 모두 접근 가능한 공유자원이다. 공유 메모리 방법은 각 프로세스가 메모리에 직접 접근하여 대량의 데이터를 쓰거나 읽을 수 있으므로 빠른 속도로 통신할 수 있다.

📄메시지 전달방법

메시지 전달방법은 협력 프로세스가 메시지를 주고받으면서 데이터를 서로 공유하는 방법이다. 메시지를 주고받기 위해 커널이 제공하는 연산 send와 연산 receive를 이용해야 한다.

  • 통신 링크
    두 프로세스가 메시지를 주고받을때, 프로세스 사이에 통신 링크가 존재한다고 볼 수 있다. 이 링크는 메시지가 지나다니는 통로이다. 통신 링크는 다양한 성질을 가질 수 있고, 다양한 형태로 구현이 가능하다. 통신 링크의 용량은 링크가 갖는 큐에 보관할 수 있는 메시지의 수를 의미한다.

  • 직접 통신
    직접통신은 두 프로세스가 직접 서로를 지정하여 메시지를 주고받는 방법이다. 송신자는 연산 send에 순시자를 직접 명시하고, 수신자는 연산 receive에 송신자를 직접 명시한다.

  • 간접 통신
    간접통신은 통신을 원하는 프로세스들 사이에 우편함을 두고 이것을 통해 메시지를 주고받는 방법이다. 간접통신에서 프로세스는 상대 프로세스 이름 대신 우편함 이름을 이용하여 메시지를 주고받으므로, 두 프로세스 사이의 통신 링크는 두 프로세스가 같은 우편함을 이용하는 경우 설정된다.



Leave a comment