프로세스가 fork()를 통해 새로운 자식 프로세스를 생성하면, 자식 프로세스는 독립적으로 실행됩니다. 이때 자식 프로세스가 종료될 때까지 부모 프로세스는 wait() 시스템 호출을 통해 자식의 종료 상태를 수거할 수 있습니다.
하지만 부모 프로세스가 wait()을 호출하지 않으면, 두 가지 상황이 발생할 수 있습니다.
1. 좀비(Zombie) 프로세스
자식 프로세스가 종료되었지만, 부모 프로세스가 wait()를 호출하지 않으면 자식의 종료 상태(exit status)가 커널에 남아 있게 됩니다.
- 자식은 종료되었지만, 부모가 wait()를 호출하지 않아 프로세스 테이블에서 완전히 제거되지 않고 남아 있는 상태를 좀비 프로세스라고 합니다.
- 좀비 프로세스는 리소스를 거의 소비하지 않지만, 너무 많아지면 프로세스 테이블이 가득 차 새로운 프로세스를 생성할 수 없게 될 수도 있습니다.
2. 고아(Orphan) 프로세스
부모 프로세스가 먼저 종료되고 자식 프로세스가 남아 있는 경우, 자식은 고아 프로세스가 됩니다.
- 리눅스와 유닉스 시스템에서는 고아 프로세스가 발생하면, 자동으로 init 프로세스(PID 1)가 이 고아 프로세스의 새로운 부모가 되어 관리합니다.
- 따라서, 현대 운영체제에서는 고아 프로세스가 방치되지 않고 자동으로 정리됩니다.
예제: Chrome 브라우저와 다중 프로세스 모델
Chrome 브라우저는 여러 개의 프로세스를 사용하는 구조입니다.
- 각 탭과 확장 프로그램은 별도의 프로세스로 실행됩니다.
- 만약 특정 탭이 충돌하더라도 전체 브라우저가 영향을 받지 않도록 설계되었습니다.
- 부모 프로세스(메인 브라우저 프로세스)가 종료되면, 자식 프로세스들(탭, 확장 프로그램)은 고아 프로세스가 될 수 있지만, 운영체제가 이를 자동으로 init 프로세스에 연결하여 정리합니다.
- Chrome은 좀비 프로세스를 피하기 위해 자식 프로세스가 종료될 때 wait() 또는 waitpid()를 호출하여 상태를 수거합니다.
프로세스간 통신
프로세스 간의 통신은 두 가지 주요 방법으로 이루어집니다: 공유 메모리 (Shared Memory)와 메시지 패싱 (Message Passing)입니다. 이들 각각은 프로세스 간 협력을 가능하게 합니다.
- 공유 메모리 (Shared Memory):
- 프로세스들이 공통의 메모리 공간을 공유합니다. 예를 들어, 한 프로세스가 공유 메모리에 데이터를 쓰면 다른 프로세스가 그 데이터를 읽을 수 있습니다. 이를 통해 두 프로세스가 간접적으로 데이터를 교환하며 협력할 수 있습니다. 이는 마치 게시판에 쪽지를 붙이고 다른 사람이 이를 읽는 방식과 유사합니다.
- 메시지 패싱 (Message Passing):
- 메시지 큐를 사용하여 프로세스 간에 직접 메시지를 전달합니다. 한 프로세스가 메시지 큐에 데이터를 넣으면 다른 프로세스가 이를 읽고 처리합니다. 이는 마치 편지를 주고받는 방식과 비슷합니다.
이 두 방법은 모두 메모리를 활용하지만, 데이터 교환 방식에서 차이가 있습니다.
협력하는 프로세스 (Cooperating Processes)
- 독립적인 프로세스들이 서로 영향을 주고받으며 협력하는 구조입니다. 중요한 점은 각 프로세스가 다른 프로세스의 실행을 방해해서는 안 된다는 것입니다. 협력은 프로세스 간의 통신을 통해 이루어집니다.
생산자-소비자 문제 (Producer-Consumer Problem)
- 이 문제는 원형 버퍼 (Bounded Buffer)를 사용한 생산자와 소비자 간의 협력을 설명합니다. 버퍼에 데이터가 가득 차면 생산자는 멈추고, 버퍼에 공간이 생기면 소비자는 이를 읽어옵니다. 반대로, 버퍼가 비면 소비자가 생산자에게 데이터를 요청하고, 생산자는 데이터를 넣습니다.
- 프로듀서 (Producer):
- 데이터를 버퍼에 넣는 역할을 합니다.
- 버퍼가 가득 차면 멈추고, 소비자가 데이터를 소비하면 다시 데이터를 넣습니다.
- 컨슈머 (Consumer):
- 데이터를 버퍼에서 꺼내서 처리하는 역할을 합니다.
- 버퍼가 비면 생산자가 데이터를 넣을 때까지 기다리고, 데이터를 꺼낸 후에는 생산자에게 데이터를 넣을 수 있게 notify합니다.
이 과정에서 notify와 wait 메커니즘을 사용하여 프로세스들이 적절히 대기하고 알림을 주고받으며 협력할 수 있습니다.
Shared Memory
프로세스 간 공유 메모리
사용자 프로세스들이 메모리를 공유할 수 있지만, 이 과정에서 운영체제는 직접적인 제어를 하지 않습니다. 공유 메모리를 사용할 때 주의해야 할 점은 **데이터 손상 (Data Corruption)**입니다. 이는 주로 writing 중에 발생합니다.
Critical Section
프로세스 1이나 2가 데이터를 쓸 때, 다른 프로세스가 동시에 데이터를 수정하려고 하면 문제가 발생할 수 있습니다. 이는 Critical Section이라 불리며, 이 시점에 다른 프로세스가 동시에 데이터를 쓸 수 없습니다. 데이터 읽기는 여러 프로세스가 동시에 할 수 있지만, 쓰기는 하나의 프로세스만 할 수 있어야 합니다.
동기화 (Synchronization)
Writing 작업을 올바르게 처리하려면, 한 프로세스만 데이터를 쓸 수 있도록 순서를 정해야 합니다. 이를 동기화 (Synchronization)라고 하며, 동기화된 환경에서는 한 프로세스가 writing을 마칠 때까지 다른 프로세스가 해당 메모리에 접근하지 못하도록 보장합니다.
Message Passing
메시지 패싱을 사용할 때는 프로세스 간에 직접 공유하는 변수가 필요하지 않습니다. 메시지를 보내고 받는 방식이기 때문에 메모리 손상 (corruption)과 같은 문제는 발생하지 않습니다.
통신 링크 (Communication Link)
예를 들어, P와 Q라는 프로세스가 통신을 원할 경우 통신 링크를 만들어야 합니다. 그러나 이 링크를 어떻게 컴퓨터 내의 리소스 간에 설정하고, 여러 프로세스 간에 연결하여 메시지를 주고받을 것인지를 고민해야 합니다. 이때 고려해야 할 사항은 링크의 수, 용량, 양방향 통신 여부 등입니다.
통신 링크의 종류
- 공유 메모리 (Shared Memory)
- 하드웨어 버스 (Hardware Bus)
- 네트워크 (Network)
이들 모두 메시지 패싱을 위한 통신 링크를 제공할 수 있습니다. 통신은 논리적으로 직접적 또는 간접적일 수 있습니다
.
직접 통신 vs 간접 통신
- 간접 통신 (Indirect Communication): 이메일처럼, 메시지를 상대방의 주소로 보내지만 실제로는 메일 시스템에 보내는 형태입니다. 메일 시스템에 접속해야만 메시지를 받을 수 있기 때문에 비동기적 (Asynchronous) 통신입니다.
- 직접 통신 (Direct Communication): 문자 메시지처럼 상대방에게 직접 보내는 형태로, 메시지가 즉시 전달됩니다. 이는 동기적 (Synchronous) 통신이라고 할 수 있습니다.
Direct Communication
프로세스 P가 메시지를 보내고, Q로부터 메시지를 받는 방식은 Direct Communication 방식으로 볼 수 있습니다. 이 방식에서는 한 쌍의 프로세스 간에 하나의 링크만 존재합니다. 즉, P와 Q 간의 직접적인 통신 링크가 설정됩니다.
Direct Communication 방식에서는 두 프로세스가 서로 직접적으로 메시지를 주고받으며, 중간에 다른 시스템이나 매개체가 개입하지 않습니다.
Indirect Communication
이것의 대표적인 예로 메일을 들 수 있습니다.
메일 박스 (Mailbox)
메일 박스는 프로세스 간 통신을 위한 공유 공간으로, 프로세스는 오직 메일 박스를 통해서만 메시지를 주고받을 수 있습니다. 메일 박스는 유니크한 ID를 가지며, 여러 프로세스가 이 메일 박스를 통해 메시지를 전달하고 받을 수 있습니다. 이를 통해 메일 박스에 여러 개의 링크를 연결할 수 있습니다.
메일 박스에 접근
메일 박스에 접근하기 위해서는 포트 (Port)를 사용합니다. 각 메일 박스는 고유의 ID를 가지며, 통신이 끝나면 메일 박스를 파괴할 수 있습니다.
메일 박스의 사용 예
예를 들어, 메일 박스 A가 있을 때, P1, P2, P3라는 세 프로세스가 이 메일 박스를 공유한다고 가정합니다. 만약 P1이 메일 박스 A에 메시지를 보낸다면, P2나 P3 중 누가 그 메시지를 읽을지 결정해야 합니다. 이를 해결하려면 여러 가지 방법을 고려해야 하며, 이 문제는 메일 박스 셰어링 (Mailbox Sharing)의 주요 과제 중 하나입니다.
확장성과 효율성
메일 박스를 통해 프로세스 간 통신의 확장성이 매우 좋습니다. 그러나, 프로세스가 2개일 때는 링크가 2개, 3개일 때는 6개와 같이 링크 수가 급격히 늘어나면서 확장성에 문제가 발생할 수 있습니다. 특히, 3개 이상의 프로세스가 메일 박스를 공유할 때, 누가 메시지를 읽을지에 대한 문제와 효율성을 고려해야 합니다.
Synchronization
블로킹과 논블로킹 메시지 전송
메시지를 전송할 때, 블로킹 전송 (Blocking Send)과 블로킹 수신 (Blocking Receive) 방식이 있습니다. 이 방식에서는 송신자가 메시지를 보내고 상대방이 메시지를 받을 때까지 작업을 하지 않습니다. 즉, 송신자는 메시지가 상대방에게 전달될 때까지 아무 일도 하지 않고 기다리는 상태입니다.
블로킹 수신은 송신자가 메시지를 보낸 후, 수신자가 메시지를 받을 때까지 송신자가 대기하는 방식입니다. 예를 들어, A라는 친구에게 메시지를 보내면, 상대방이 메시지를 받기 전까지 아무 일도 하지 않는 것입니다. 메시지가 오기를 기다리면서 멈춰있는 상태입니다.
논블로킹 (Non-blocking)은 비동기 (Asynchronous) 방식으로, 메시지가 상대방에게 전달될 때까지 기다리지 않고 다른 작업을 계속할 수 있는 방식입니다. 이는 상대방이 메시지를 받을 때까지 가만히 있는 블로킹 방식과 대조적으로, 논블로킹 방식에서는 다른 작업을 하면서 메시지가 전달되기를 기다리는 방식입니다.
비동기 통신 (Asynchronous Communication)에서는 메시지를 송신한 후, 즉시 다른 작업을 진행할 수 있습니다. 이는 동기화되지 않은 방식으로, 송신자가 메시지를 보내고 상대방이 반응하기를 기다리는 것이 아니라 다른 작업을 계속하면서 메시지가 처리되기를 기다리는 방식입니다.
다양한 조합 가능성
메시지를 주고받는 과정에서는 동기화 방식 (synchronous)과 비동기 방식 (asynchronous)이 혼합될 수 있습니다. 이를 통해 프로세스들 간에 rendezvous(상호 통신) 방식이 필요하며, 각 프로세스는 메시지를 주고받을 때 동기화 혹은 비동기화 방식으로 동작할 수 있습니다.
프로듀서-소비자 문제
프로듀서와 소비자 간의 통신에서, 프로듀서가 데이터를 넣고 소비자가 데이터를 읽는 방식입니다. 이 때, 프로듀서가 데이터를 넣을 때와 소비자가 이를 읽을 때 서로의 작업이 동기화되어야 하지만 현실적으로 프로세스는 원하는 때에 넣고 읽고 합니다. 이는 완벽하게 동기화된 상태가 아니며, 프로세스들이 각각의 작업을 독립적으로 실행하는 방식입니다.
버퍼링
프로듀서-컨슈머 문제와 버퍼
프로듀서-컨슈머 문제에서 링크와 버퍼를 사용합니다. 프로듀서는 데이터를 버퍼에 넣고, 컨슈머는 데이터를 버퍼에서 읽어 갑니다. 이때, 버퍼는 메시지를 일시적으로 저장하는 역할을 합니다.
제로 용량(Zero Capacity) 큐
제로 용량 큐는 메시지가 없을 때까지 리시버(소비자)가 기다려야 하는 상태입니다. 큐의 용량이 0이면 프로듀서가 데이터를 보내려 해도 받을 공간이 없기 때문에, 리시버가 데이터를 읽기 전까지 프로듀서는 대기해야 합니다.
용량 제한(Bounded Capacity) 큐
Bounded Capacity는 큐에 제한된 용량이 있다는 것을 의미합니다. 만약 큐가 가득 찼다면, 프로듀서는 큐에 더 이상 데이터를 넣을 수 없습니다. 이때, 프로듀서는 큐에 공간이 생길 때까지 기다려야 하며, 공간은 리시버가 데이터를 읽어갈 때 비워지게 됩니다. 즉, 큐가 가득 찼을 때는 프로듀서가 대기하게 됩니다.
무제한 용량(Unbounded Capacity) 큐
Unbounded Capacity는 큐의 크기가 무한히 확장될 수 있음을 의미합니다. 큐의 용량에 제한이 없기 때문에, 프로듀서는 데이터를 계속해서 넣을 수 있습니다. 이 경우, 큐가 가득 찰 걱정 없이 데이터를 추가할 수 있습니다.
'IT 프로그래밍 > 운영체제' 카테고리의 다른 글
[FT] [운영체제] 프로세스의 생성과 삭제 (0) | 2025.03.28 |
---|---|
[FT][운영체제] 프로세스와 스레드 (0) | 2025.03.28 |
[운영체제] 스케쥴러 (0) | 2025.03.25 |
[운영체제] 프로세스의 관리 (0) | 2025.03.25 |
HTTP, SSL 설명 (0) | 2024.08.21 |