CS/운영체제

[CS/운영체제] 프로세스 관리와 통신

연유뿌린빙수 2025. 10. 14. 21:33

PCB(Process Control Block)

우리의 CPU는 한 번에 하나의 프로세스만 실행할 수 있다.
하지만 사용자 입장에서는 CPU가 매우 많은 데이터를 동시에 빠르게 처리하는 것처럼 보인다.
이는 CPU가 매우 빠른 속도로 여러 프로세스를 번갈아가며 실행하기 때문이다.
즉, CPU가 짧은 시간 단위로 프로세스를 전환하면서 처리하기 때문에, 결과적으로 동시에 여러 작업이 수행되는 것처럼 보이는 것이다.

 

그렇다면 이러한 CPU에서 프로세스의 우선순위나 자원 배분 등을 어떻게 관리할 수 있을까?
이를 위해 필요한 것이 바로 PCB(Process Control Block) 이다.

운영체제는 빠르게 번갈아 수행되는 프로세스들의 실행 순서를 관리하고, 각 프로세스에 CPU 및 기타 자원을 효율적으로 배분한다.
이때 PCB는 프로세스의 상태와 관련된 모든 핵심 정보를 저장·관리하기 위한 자료구조로 사용된다.

 

PCB는 프로세스와 관련된 정보를 저장하는 구조체(자료구조) 이다.
운영체제는 PCB를 통해 각 프로세스를 식별하고, 문맥 교환(context switching) 시 필요한 정보를 저장하거나 복원한다.

PCB에 들어간 정보는 다음과 같다.

  • PID(Process ID)
    프로세스를 식별하기 위한 고유한 번호
  • Process State
    프로세스의 현재 상태(생성, 준비, 실행, 대기, 종료 등)
  • Pointer
    메모리 상에서 각 프로세스가 저장된 위치 정보.
    프로세스마다 메모리 주소가 다르기 때문에 PCB에는 해당 프로세스의 베이스 레지스터(Base Register), 한계 레지스터(Limit Register) 값 등이 저장된다.
    또한 프로세의 주소 공간을 관리하기 위한 페이지 테이블(Page Table) 정보도 포함된다.
  • Priority
    프로세스의 우선순위 정보를 저장
  • CPU Registers
    프로세스가 CPU를 사용하다가 중단될 때의 레지스터 값 (예시. PC(Program Counter, 누산기 등)
    프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원한다. 그래야만 이전까지 진행했던 작업들을 그대로 이어 실행할 수 있기 때문이다.
  • I/O information
    해당 프로세스에 할당된 입출력 장치나, 열려있는 파일 등의 정보가 포함된다.
  • Accounting Information
    프로세스의 CPU 사용 시간, 실행 횟수 등 자원 사용과 관련된 통계 정보
  • PC(Program Counter)
    프로그램 계수기. 프로세스가 다음에 실행할 명령어의 주소를 나타냄
  • CPU 스케줄링 정보
    프로세스가 언제, 어떤 순서로 CPU를 할당 받을지에 대한 스케줄링 정보

PCB에 저장되는 프로세스 상태에 대하여 좀더 자세히 알아보자.

 

프로세스의 상태

 

프로세스의 상태는 일반적으로 생성 -> 준비 -> 실행 -> 대기 -> 종료 의 단계로 구분이 된다.

운영체제는 이 상태 정보를 PCB에 저장하여, 각 프로세스의 현재 상태를 추적하고 관리한다.

  1. 생성 상태(New / Created)
    프로세스가 메모리에 적재되기 전, 즉 생성 중인 상태이다.
    운영체제가 새로운 프로세스를 만들고, PCB를 생성하며 초기 자원을 할당하는 단계이다.
    ex. 사용자가 프로그램을 실행, 다른 프로세스가 새로운 프로세스를 생성
    - PCB 할당, 메모리 공간 확보, 필요한 초기 자원(파일 핸들, I/O 등) 요청, 준비 상태로 전이될 조건 검사
  2. 준비 상태(Ready)
    프로세스가 CPU를 할당받기 위해 대기 중인 상태이다.
    실행 가능한 상태이지만, CPU를 아직 배정받지 못한 상태이다.
    ex. 여러 개의 프로세스가 동시에 실행을 기다리는 "준비 큐(Ready Queue)"에 들어있는 상황
    - 스케줄러가 어떤 프로세스에 CPU를 줄지 결정할 때까지 대기, PCB에 우선순위(Priority), 대기시간, 상태 등이 기록됨
  3. 실행 상태(Running)
    CPU가 해당 프로세스를 실행 중인 상태로, 실제로 명령어들이 CPU에서 수행되는 단계이다.
    PC에 저장된 명령어를 CPU가 실행하고, 레지스터 값, 연산 결과 등이 갱신된다.
    실행 중인 프로세스는 다음과 같은 이유로 다른 상태로 전환될 수 있다:
  • I/O 요청 → 대기 상태(Waiting)
  • 타임 슬라이스(time slice) 종료 → 준비 상태(Ready)
  • 프로세스 종료 → 종료 상태(Terminated)

4. 대기 상태(Waiting / Blocked)
프로세스가 I/O 작업이나 특정 이벤트를 기다리는 상태이다.
CPU는 해당 프로세스가 기다리는 동안 다른 프로세스에게 양보한다.
ex. 세마포어 등 동기화 자원을 기다림
- CPU는 다른 프로세스에 할당됨, 해당 이벤트가 완료되면 준비 상태로 복귀

 

5. 종료 상태 (Terminated / Exit)
프로세스의 실행이 끝나거나, 운영체제 혹은 사용자가 강제로 종료시킨 상태
프로세스의 실행이 끝나거나, 운영체제 혹은 사용자가 강제로 종료시킨 상태이다.
- PCB 제거, 점유하던 메모리와 자원 해제, 종료 코드(Return Code) 전달




Context Switching

운영체제의 개념에서 Context(문맥) 이란,
하나의 프로세스가 실행을 재개하기 위해 반드시 기억해야 하는 정보를 의미한다.

 

 

즉, 프로세스의 실행 상태를 다시 복원하기 위해 필요한 모든 정보가 문맥(Context)에 해당한다.

하나의 프로세스의 문맥은 해당 프로세스의 PCB(Process Control Block) 에 의해 표현된다.


PCB에 기록되어 있는 정보(레지스터 값, 프로그램 카운터, 메모리 정보 등) 전체를 문맥이라고 봐도 무방하다.

일반적으로 Context Switching(문맥 교환) 은 다음과 같은 상황에서 발생한다.
-> 인터럽트(Interrupt) 가 발생한 경우, 현재 실행 중인 프로세스의 CPU 사용 시간이 모두 소모된 경우, 입출력(I/O) 작업을 위해 프로세스가 대기 상태로 전환되는 경우 등등 ...

 

이때 운영체제는 현재 실행 중인 프로세스의 문맥을 PCB에 저장하고,
새로 실행할 프로세스의 문맥을 복원하여 CPU에서 실행을 이어가도록 한다.

 

이 과정을 통해 CPU는 여러 프로세스를 빠르게 번갈아 실행할 수 있으며,
결과적으로 멀티태스킹(multitasking) 환경이 구현된다.

Context Switching을 표현하면 위와 같다.


Overhead

프로세스의 실행 과정에서는 오버헤드(Overhead) 를 감수해야 하는 상황이 반드시 존재한다.

예를 들어, 프로세스가 실행 중 입출력(I/O) 이벤트가 발생하면 프로세스는 대기(Waiting) 상태로 전환된다.
이때 CPU가 아무런 작업도 하지 않고 단순히 대기하도록 두는 것은 비효율적이다.

따라서 운영체제는 CPU가 쉬지 않고 계속 작업을 수행할 수 있도록,
다른 프로세스를 실행시키는 방식으로 자원을 효율적으로 활용한다.
이를 위해 필요한 과정이 바로 Context Switching(문맥 교환) 이다.

즉, CPU가 가능한 한 항상 어떤 프로세스든 실행 중인 상태를 유지하도록 함으로써
CPU의 유휴 시간을 최소화하고, 사용자에게 더 빠른 응답성과 처리 속도를 제공하는 것이다.

 
 

그러면 프로세스끼리 통신은 어떻게 할까??

IPC(Inter-Process Communication)

프로세스는 독립적으로 실행된다.
CPU에서 프로세스에 대한 할당만 보아도 독립적으로 실행됨을 알 수 있다.
(즉, 독립되어있다는 것은 다른 프로세스에게 영향을 받지 않는다는 것이다. 스레드는 프로세스 안에서 자원을 공유 받으므로 이와는 별개이긴 함)

하지만, 이런 독립적인 프로세스끼리도 당연히 통신 필요한데

그래서 존재하는 것이 IPC 이다.


IPC 종류

1. 익명 PIPE

익명 파이프는 단방향(half-duplex) 통신만 가능한 구조이다.
즉, 한쪽 방향으로만 데이터 전송이 가능하다.

그래서 양방향 통신을 하고자 할 경우, 두 개의 파이프(pipe) 를 만들어야 한다.

익명 파이프는 통신할 프로세스가 서로 명확히 연관되어 있는 경우,
예를 들어 부모-자식 프로세스 간 통신에 주로 사용된다.

 

 

2. Named PIPE(FIFO)

네임드 파이프(Named Pipe 또는 FIFO) 는
서로 전혀 관계없는 프로세스들 간의 통신을 가능하게 하는 파이프이다.


즉, 익명 파이프의 확장된 형태로, 이름이 있는 파일(경로) 을 통해 통신이 이루어진다.

이를 통해 부모-자식 관계가 아닌 완전히 독립적인 프로세스 간에도 데이터 교환이 가능하다.


다만, 익명 파이프와 마찬가지로 동시에 읽기/쓰기를 수행하는 것은 불가능하며,
pipe1, pipe2처럼 송신용과 수신용 파이프를 분리하여 설계해야 한다.

 

 

3. Message Queue

메시지 큐는 데이터의 흐름이 아닌, 메모리 공간 기반의 통신 방식이다.


기본적인 입출력 동작은 네임드 파이프와 유사하지만,
메모리 내부에 메시지 단위의 큐(queue) 를 생성하여 여러 프로세스가 동시에 접근할 수 있다.

각 데이터(메시지)는 고유한 식별 번호(ID) 를 가지며,
프로세스들은 이 번호를 통해 원하는 메시지만 선택적으로 읽거나 쓸 수 있다.

 

예를 들어, 프로세스 A가 B, C, D와 통신하려는 경우
공유된 메시지 큐 공간에 데이터를 번호별로 저장하고,
다른 프로세스들이 해당 번호를 이용해 데이터를 읽는 방식으로 동작한다.


위에서 까지가 통신을 이용한 설비라면, 공유 메모리는 데이터 자체를 공유하도록 지원하는 설비다.

 

 

4. 공유 메모리

공유 메모리는 데이터 자체를 공유하도록 지원하는 방식이다.
일반적으로 프로세스의 메모리 공간은 서로 완전히 분리되어 있으며,
다른 프로세스가 임의로 접근하지 못하도록 보호된다.

하지만 여러 프로세스가 동일한 데이터를 사용할 필요가 있는 경우,
운영체제는 특정 메모리 영역을 공유 메모리로 할당하여 공동 접근을 허용한다.

 

프로세스가 공유 메모리를 요청하면 커널은 메모리 영역을 생성하고,
해당 영역을 여러 프로세스의 주소 공간에 매핑(mapping) 시켜준다.


이후 모든 프로세스는 해당 메모리 영역을 통해 데이터를 직접 주고받을 수 있다.

이 방식에서 세마포어(Semaphore) 는 매우 중요하다.


공유 자원에 동시에 접근하려는 문제(경쟁 상태, race condition)를 방지하기 위해
세마포어나 뮤텍스(Mutex) 를 사용하여 동기화를 수행해야 한다.

 

일반적으로 공유 메모리 통신에서는 두 가지 역할이 존재한다:

  • 생산자(Producer) : 공유 메모리(버퍼)에 데이터를 생성하고 저장
  • 소비자(Consumer) : 공유 메모리에서 데이터를 읽고 소비

이때 동기화(synchronization) 가 필수적으로 필요하다.
이에 대한 자세한 내용은 동기화 메커니즘(세마포어, 모니터 등)에서 나중에 다룰테니 일단은 여기까지만 정리하자!!!

 

 

5. 메모리 맵

메모리 맵은 공유 메모리와 유사하게 메모리를 공유하지만,
파일을 메모리에 매핑(mapping) 하여 통신을 수행한다는 점이 다르다.

 

즉, 공유 매개체가 “파일 + 메모리”의 형태로 결합된 구조이다.

파일을 메모리에 직접 연결함으로써,
프로세스들이 파일 I/O를 수행하지 않고도 데이터를 읽고 쓸 수 있다.


주로 대용량 데이터를 여러 프로세스 간에 공유해야 할 때 사용된다.

 

 

6. 소켓

소켓은 네트워크를 기반으로 한 통신 방식이다.
로컬 환경뿐만 아니라, 원격(Remote) 환경에서도 프로세스 간 통신을 지원한다.

일반적으로 클라이언트-서버 구조로 동작하며,
다음과 같은 절차로 통신이 이루어진다:

서버(bind, listen, accept) <-> 클라이언트(connect)
클라이언트: connect

소켓을 통해 서로 다른 시스템 간에도 데이터를 주고받을 수 있으며,
TCP/IP 또는 UDP 기반의 통신이 가능하다.

 

또한 소켓 통신에서도 동기화 및 자원 보호를 위해
세마포어(Semaphore)나 뮤텍스(Mutex) 같은 동기화 기법이 함께 사용된다.


이를 통해 공유 자원에 대해 동시에 하나의 프로세스만 접근하도록 제어한다.