✅ 1. 생산자-소비자 문제
(1) 문제 정의

- 협력 프로세스: 생산자 프로세스와 소비자 프로세스를 의미할 수 있으며, 사이에 버퍼를 두고 있음.
- 생산자: 버퍼에 데이터를 넣는 프로세스
- 소비자: 버퍼에서 데이터를 꺼내는 프로세스
- TIP: 거의 모든 프로세스 통신이 해당 생산자-소비자 구조를 띄고 있으며, 중간에 버퍼는 공유 데이터의 일부로써, 공유 데이터는 버퍼, 전역 변수, 파일 등 프로세스들이 함께 사용하는 모든 것을 의미하는 개념임.
- TIP: 또한, 해당 프로세스 간 통신(IPC) 는 버퍼라는 형태의 공유 데이터를 거쳐서 일어나기 때문에 알아야함.
(2) 문제 해결 조건

- 생산자-소비자 문제를 해결하기 위해 반드시 지켜야 하는 두 가지 핵심 조건을 의미한다.
- 버퍼에 여러 프로세스가 동시에 접근할 수 없음: 버퍼 자체는 프로세스들이 공유하는 공유 데이터이기 때문에 동시에 접근을 하게 되면 데이터의 일관성이 무너질 수 있음.
- 상호배제 필요: 즉, 상호배제를 통해 프로세스(협력 프로세스)가 동시에 임계영역을 수행하지 못하도록 막아줘야함.
- 버퍼의 크기가 유한 (유한 버퍼 문제): 버퍼가 가득 찬 경우에는 더 이상 데이터를 넣을 공간이 없으므로, 생산자는 대기를 해야하고 반대로 버퍼가 빈 경우에는 더 이상 가져갈 데이터가 없기 때문에 소비자는 대기를 해야함.
- 동기화 필요: 해당 버퍼에 데이터가 일관된 정보를 가지도록 맞추기 위해서는 버퍼의 잔여량, 점유 여부 같은 상태 정보가 모든 프로세스에게 일관되게 보이도록 만들어야함.
- TIP: 동기화란? 두 개 이상 개체가 동일한 정보를 가지도록 맞추는 작업을 의미함. ( 처리 순서를 맞춤으로써 해결 )
(3) 생산자-소비자 문제 - 해결 방법

- 상호배제 해결: 세마포어를 통해서 문제를 해결하며, 세부적으로는 생산자나 소비자는 임계영역에 접근 할 때 mutex 값을 확인 한 뒤, mutex = 1 인 경우 임계영역에서 처리를 하고 만약 mutex = 0 은 이미 다른 프로세스가 임계영역에서 처리를 진행하고 있으므로, 대기 큐에 들어가게 됨.

- 버퍼가 가득 찬 경우 동기화: 기초적인 세마포어의 개념에 empty 라는 논리적으로 버퍼의 상태가 비어있는가에 따른 상태를 정의하여 버퍼에 대한 접근을 empty 상태값에 따라 제어 할 수 있음.
- empty: 버퍼중에 비어있는 칸의 개수를 의미한다.
- empty 초기값: 버퍼의 크기인 N 으로 초기화
- 비어있는 칸의 개수를 통해서 접근을 제어하며, 0인 경우 버퍼가 꽉 참을 의미하고 0 이상의 정수인 경우에는 버퍼가 그만큼 비어있다는 것을 의미하므로, 사용 가능한 버퍼의 수를 나타낼 수 있음.
- 또한, 이 연산은 기본 도구(세마포어)를 조립해서 만든 상위 레벨의 알고리즘(유한 버퍼 문제 해결) 이라고 볼 수 있음.
- 핵심: 기존의 P, V 연산에 full, empty 인지 파악을 하는 연산을 통해서 프로세스를 대기 시키는 것임.

- 버퍼가 빈 경우 동기화: 기초적인 세마포어의 개념에 full 라는 논리적으로 버퍼의 상태가 차있는가에 따른 상태를 정의하여 버퍼에 대한 접근을 full 상태값에 따라 제어 할 수 있음.
- full: 버퍼중에 채워져 있는 칸의 개수를 의미한다.
[ 정리 ]
- 소비자: full 세마포어를 보고 0인 경우 채워져 있는 칸의 개수가 없는 경우이므로, 소비자는 더 이상 꺼낼 데이터가 없다고 판단을 해 대기 상태로 들어가게 된다. 또한, 0이 아닌 경우 해당 버퍼에서 데이터를 꺼내며 empty 의 값을 하나 늘려주게 됨.
- 생산자: empty 세마포어를 보고 비어있는 칸의 개수를 파악 한 뒤 0일 경우 데이터가 꽉찼는 것을 인지게 되며, 데이터를 버퍼에 못넣고 대기하는 상태로 접어들게 된다. 이후, empty 의 값이 1 이상일 경우 데이터를 버퍼에 넣으면서 empty 의 값을 줄여주게 되는 원리이다.

- 상호배제 해결: mutex 를 활용
- 동기화 해결: empty, full 활용
✅ 2. 판독기-기록기 문제
(1) 문제 정의

- 판독기: 데이터를 읽기만 하는 프로세스를 의미한다.
- 기록기: 데이터를 쓰기만 하는 프로세스를 의미한다.
- 생산자-소비자 구조와 다른점: 생산자-소비자 구조는 버퍼를 통해서 데이터 삽입 또는 꺼내는 역할을 하기 때문에 데이터를 지워주는 과정이 필요하기 때문에 기록기만 존재하는 구조로 볼 수 있음.
- 즉, 생산자-소비자 둘 다 공유자원에 대해서 쓰거나 읽기 작업에 변화를 주는 특징이 있음.
- ** 반면, 판독기-기록기 문제는 판독기의 읽는 과정에서 단순히 읽기만 하기 때문에 공유자원에 변화를 주지 않음. **
- 또한, 공유자원에 변화를 주지 않기 때문에 여러 판독기 프로세스들은 동시에 공유자원에 접근해서 데이터를 읽을 수 있음.
(2) 문제 해결 조건

- 조건1: 하나의 기록기가 공유자원에 데이터를 쓰는 중에는 다른 기록기나 판독기는 공유자원에 접근 할 수 없음.
- 즉, 공유자원에 데이터를 쓰는 동안에는 누구도 접근 할 수 없다는 의미가 된다.
- 조건2: 또한, 데이터를 읽는 동안에는 누구도 데이터를 쓸 수 없음.
- 조건3: 여러 판독기는 동시에 공유자원에서 데이터를 읽을 수 있음.
- 즉, 판독기가 읽는 중 새로운 판독기 읽기 시도는 가능하며, 판독기가 읽는 중에는 기록기는 대기상태여야 함.
- ** 또한, 기록기가 1번에 데이터를 삽입 중에 판독기가 2번에 데이터를 읽고 싶다고 했을 경우 기록기와 판독기의 작업이 겹치지 않기 때문에 읽게 할 수도 있음. ( 가능하거나 불가능함 ) -> 정책에 따라서 달라 질 수 있음. **
(3) 제1 판독기-기록기 문제

- 제1 판독기 기록기 문제: 판독기가 공유자원에 접근 중이라면 기록기보다 판독기에 우선순위를 주는 방식임.
- 즉, 대기 큐에 기록기가 들어가있다고 해도 판독기가 계속해서 우선순위를 가져가는 원리임.
- 문제점: 기록기가 기아상태가 유발이 될 수 있음. 즉, 기록기가 계속해서 대기상태로 대기 할 수 있는 문제가 있음.
- 정리: 판독기(읽기) 가 공유자원에 접근에 대한 우선순위를 항상 주는 방식이라, 기록기(쓰기) 평생 못할 수 있음.
(4) 제1 판독기-기록기 문제 - 세마포어를 이용한 해결

- 기록기 임계영역: 기록기(쓰기) 작업 자체는 임계 영역으로 간주 할 수 있음.
- 판독기 임계영역: 판독기(읽기) 작업 자체는 임계 영역으로 간주 할 수 있음.
- 상호배제: 세마포어(wrt) 초깃값 1로 두고 상호배제 문제를 해결하고 있음.
- ** 문제는 판독기는 읽기 작업이기 때문에 다른 판독기도 읽기 작업이 동시에 가능하기 때문에 들어올 수 있게 해줘야함. **

- 여러 판독기의 공유자원 접근: rcount 일반 변수를 선언 한 뒤, rcount 가 1인 경우에는 제일 첫 번째 판독기가 들어온 경우로 볼 수 있기 때문에 먼저 P(wrt) 를 통해서 기록기가 현재 공유 자원을 사용하고 있는지를 판단하게 됨.
- 이후, 만약 사용하고 있지 않다면 공유자원에 대한 읽기를 수행하게 된다.
- 또한, 이때 다른 판독기가 들어오게 되면 rcount 가 1이 증가하기 때문에 위와 같은 if (rcount == 1) 에 대해서 false 이므로, 그냥 통과를 하며 판독기를 읽게 되는 과정임.
- 마지막으로 공유 자원을 다읽게 되면 rcount 를 -1 감소함으로써 특정 판독기의 읽기 작업이 끝남을 명시하게 됨.
- 문제점: 판독기(읽기) 가 공유자원에 접근에 대한 우선순위를 항상 주는 방식이라, 기록기(쓰기) 평생 못할 수 있음.

- 결론: 이와 같이 2개의 세마포어와 일반변수를 통해서 제1 판독기-기록기 문제를 해결 할 수 있음.
- 정리: P(wrt) 세마포어를 활용해서, 기록기나 판독기가 임계영역을 수행중임을 검사하며, 이때 판독기의 코드에는 rcount 변수를 통해서 제일 처음 판독기가 임계영역을 수행하기 위해 들어온다면 rcount 의 값은 1이므로, P(wrt) 를 수행하게 된다.
- 이때, P(wrt) 는 기록기가 기록을 하는 중인가를 보고, 만약 안하고 있다면 임계영역을 판독기가 수행을 하게 되는데, 이 과정에서 새로운 기록기와 판독기가 들어온다고 하면 기록기는 P(wrt) 에 의해서 판독기가 임계영역을 수행 중임을 판단해 대기 상태로 들어가지만, 새로운 판독기는 rcount = rcount + 1; 을 통해 정수값 2가 되므로, P(wrt) 코드를 실행하지 않고 바로 임계영역에서 공유자원을 읽을 수 있기 때문에 이는 여러 판독기가 하나의 임계영역에서 읽을 수 있게 도와주는 원리이다.
- ** 이렇기 때문에 기록기는 무한으로 대기를 할 수 있는 문제가 발생 할 수 있음. **
(5) 제2 판독기-기록기 문제

- 제2 판독기-기록기 문제: 판독기가 공유자원에 접근 중이라면 판독기보다 기록기에 우선순위를 주는 방식임.
- ** 즉, 대기 중인 기록기가 있다면 새로운 판독기는 공유자원에 접근이 불가능한 원리임. **
- 문제점: 판독기가 기아상태(오랜 대기시간)가 될 수 있으며, 이때문에 판독기의 병행성이 떨어질 수 있음.
(6) 제2 판독기-기록기 문제 - 세마포어를 이용한 해결

- P(rd) 세마포어: 기록기에게 우선순위를 주기 위해서 기록기가 먼저 들어와 있는지 아닌지 체크를 해주는 용도임.
- wcount: 처음 기록기가 들어올 당시 wcount 의 값이 1로 되어, P(rd) 를 통해 처음 들어온 기록기가 임계영역을 먼저 수행하게 된다. 이후, 다음 기록기가 들어오게 된다면 wcount 의 값이 +1 되어 항상 1이 아닌 더 높은 수로써 P(rd) 를 skip 한 상태로 P(wrt) 를 통해 판독기가 임계영역을 수행중인가를 파악 한 뒤 공유자원을 쓰는 원리이다.
- 정리: 판독기-기록기 문제는 특정 상황에서 판독기에 우선순위를 주는 형태의 문제와 기록기에 우선순위를 주는 형태의 문제로써 정의 할 수 있음.
✅ 3. 프로세스 간 통신
(1) 프로세스 간 통신 (IPC)

- IPC: 병행 프로세스(협력 프로세스)가 서로 데이터를 공유하는 방법을 의미한다.
- 대표적으로 공유 메모리 방법, 메시지 전달방법 등이 있음.
- ** 두 방법은 독립적이지 않기 때문에 하나의 운영체제 내에서 두 방법을 함께 사용이 가능함. **
(2) 공유 메모리 방법

- 공유 메모리 방법: 협력 프로세스가 공유 메모리를 통해서 동일한 변수를 사용하는 방법을 의미한다.
- 공유 메모리 예: 생산자-소비자 문제의 유한 버퍼, 판독기-기록기 문제의 공유자원을 공유 메모리 방식으로 해결이 가능.
- 대량 데이터 교환: 커널을 거치지 않고 데이터에 직접 접근하기 때문에 매우 빠른 것이다. 쉽게 말해, 일단 두 프로세스가 특정 메모리 영역을 공유하도록 설정(Mapping) 하고 나면, 그 이후에는 OS 의 개입이 전혀 없고 그냥 메모리에 글을 쓰듯 데이터를 넣으면 상대방이 즉시 볼 수 있는 원리임. 그렇기 때문에 속도가 빨라 대량의 데이터 교환에 용이함.
- 통신상 발생 가능 문제 해결: 운영체제의 개입이 없기 때문에 공유 메모리에 대한 변수에 대한 통신상 발생 가능한 문제를 고려해서 응용 프로그램을 만들어야 한다는 단점이 있음.
- ** 즉, 개발자가 직접 세마포어(Semaphore)나 뮤텍스(Mutex)를 사용해 동기화, 상호배제를 처리하도록 코드를 짜야 함. **
(3) 메시지 전달방법

- 메시지 전달방법: 협력 프로세스가 커널 시스템 콜을 통해서 메시지를 주고받는 방법을 의미함.
- 소량 데이터 교환에 적합: 사용자 공간에서 커널 공간으로 데이터 복사 후 커널 공간에서 사용자 공간으로 데이터가 복사 되는 방식이기 때문에 대량의 데이터 교환은 공유 메모리 방식 매우 느릴 수 있음.
- 통신상 발생 가능 문제 해결: 운영체제가 직접 동기화, 상호배제, 주소 지정, 버퍼링 등 싹 관리를 해주기 때문에 통신상 발생할 수 있는 문제에 대해서 안전함.
(4) 메시지 전달방법 - 논리적 구조

- 통신 링크: 프로세스 사이에 메시지가 오가는 "논리적인 연결 통로" 를 의미한다.
- 통신 링크의 구현 형태: 연결 대상, 두 프로세스 사이 링크 개수, 방향성, 용량 등을 정의해 통신 링크를 정의 할 수 있다.

- 통신 링크의 용량(무한): 중간의 큐, 버퍼 크기가 무한한 경우이며, 대기없이 바로 보낼 수 있음.
- 통신 링크의 용량(유한): 중간의 큐, 버퍼 크기가 유한한 경우이며, 큐가 가득 차면 대기를 해야함.
- 통신 링크의 용량(O): 중간의 큐가 아예 없는 경우이며, 송신자는 수신자가 메시지를 받을 수 있는 상태가 되기까지 기다렸다가 보내줘야함.

- 직접통신: 두 협력 프로세스가 직접 서로를 지정하여 양방향으로 메시지를 전달하는 방식임.
- 오직 하나의 링크: A와 B 사이에 전용 논리적인 회선이 하나 깔리는 개념
- 두 프로세스 사이만 연관: 해당 회선은 C나 D 등은 절대 끼어들 수 없는 1:1 논리적인 회선임.
- 양방향: A와 B 사이의 회선에서 송신과 수신이 독립적인 통로 아니면 하나의 통로를 매우 빠륵 ㅔ나누어 써서 실사간으로 서로 동시에 통신을 하는 방식을 의미함.

send(P, message) : 프로세스 P에게 메시지를 보낸다.
receive(Q, message) : 프로세스 Q로부터 메시지를 받는다.
- 대칭형 주소 지정: 대화하는 두 프로세스가 서로의 이름(주소)를 모두 알고 있어야 하는 방식이며, 보낼 때와 받을 때 누구에게 보낼 것인지와 받을 것인지를 명시를 해줘야함. 양방향 통신이 아주 명확해지지만, 상대방의 주소를 미리 알아야 하므로 프로그램의 유연성이 떨어질 수 있음.
- 즉, 프로세스 A가 프로세스 B에세 데이터를 보낼 때 send(B, m) 을 통해서 시스템 콜을 하게 되면, 프로세스 B에서는 receive(A, m) 을 통해서 보낸 사람의 이름을 명시해서 시스템 콜을 해주어야 받을 수 있음.
- ** 결론은 프로세스 B에 항상 receive(A, m) 과 같이 누구에게 받는 것인지와 계속해서 메시지가 도착했는가를 receive() 시스템 콜을 통해서 확인 및 받아와야함. 매우 비효율적임. **
- 대칭형 방식은 애초에 보안과 오류 방지에 올인한 방식으로, receive(A, m) -> A 말고는 아무하고도 말 안한다는 강력한 필터링을 하기 위한 목적으로 사용한다고 보면 됨.
송신자 (Client 역할): 여전히 보낼 대상을 명시합니다.
- send(P, message) : "나는 프로세스 P에게 메시지를 보낼 거야."
수신자 (Server 역할): 누가 보낼지 모르니 이름을 비워둡니다.
- receive(id, message) : "누구든 메시지를 보내면 일단 받을게. 그리고 보낸 놈의 이름은 id라는 변수에 좀 담아줘."
- 비대칭형 주소 지정: 대칭형은 양쪽 다 이름을 적어야 하는 방식이지만, 해당 비대칭형 방식은 한쪽만 이름을 적을 수 있음.
- ** 위의 대칭형 주소 지정 방식의 receive(A, m) 와 같이 A 라는 보낸 프로세스의 이름(주소)를 계속해서 하드 코딩 방식을 수신자 츶에서 receive(id, message) 를 통해서 유연하게 개선 한 방식임. **
- 쉽게 말해, 메시지를 보내고 받을 때 주소도 같이 받는 방식이라고 보면 됨.

- 간접통신: 기존 직접통신 방식은 상대방을 직접 지정해서 통신을 했지만, 간접통신 방식은 상대방을 지정하지 않고, A 프로세스가 특정 우편함에 메시지를 넣으면 B 프로세스 해당 우편함에서 메시지를 꺼내가는 방식임.
- 특정 프로세스가 여러개의 우편함을 이용하면 특정 프로세스와 연결 된 여러 개의 통신 링크가 존재 할 수 있음.

- 우편함이 수신 프로세스에 소속: 수신 프로세스에 소속될 경우 프로세스 자체 내부에 우편함을 가지고 있는 경우로써 다른 프로세스들은 send() 만 할 수 있으며, 수신 프로세스만 receive() 를 통해 꺼낼 수 있음.
- 우편함이 운영체제에 소속: 우편함이 운영체제에 소속된 경우 프로세스들은 공용 우편함으로써 send() 또는 receive() 가능.
[ 개인적인 해석 ]
🔹 파이프(pipe)
- 단방향
- 용량 제한 있음
- 1:1 통신
👉 커널이 이렇게 만들어둔 구조 - pipe()
🔹 메시지 큐
- 다대다 가능
- 큐 기반 (용량 있음)
- 간접 통신
👉 이것도 커널이 정의한 방식 - msgget()
🔹 소켓(socket)
- 양방향
- 네트워크까지 가능
- 스트림 기반
👉 이것도 이미 설계된 링크 특성 - socket()
...
- 커널이 이미 IPC 모듈들을 설계해놓은 상태이며, 이 중 하나를 골라서 시스템 콜로 사용하는 구조임.
- 즉, 방향성, 용량, 연결방식 등을 모두 구현을 해놓은 상태이며, 이것을 골라서 사용하는 개념으로 보면 됨.
'방송통신대학교 > ⚙️운영체제' 카테고리의 다른 글
| [운영체제] 7강 - 교착상태(2) (0) | 2026.04.02 |
|---|---|
| [운영체제] 6강 - 교착상태(1) (0) | 2026.03.20 |
| [운영체제] 4강 - 병행 프로세스(1) (0) | 2026.03.06 |
| [운영체제] 3강 - 프로세스 스케줄링 (0) | 2026.02.27 |
| [운영체제] 2강 - 프로세스와 쓰레드 (0) | 2026.02.19 |