OSTEP 프로세스 추상화: 프로그램·상태·PCB·컨텍스트 스위치

반응형

OSTEP의 「The Abstraction: The Process」를 읽고 다시 정리했다. 기존 글은 제목과 달리 CPU 스케줄링 정책을 설명하고 있었는데, 그 내용은 CPU 스케줄링 기초 글과 겹쳤다. 여기서는 한 단계 앞선 질문, 운영체제는 실행 중인 프로그램을 어떻게 하나의 ‘프로세스’로 다루는가에만 집중한다.

한 문장으로 답하면

프로그램은 디스크에 저장된 명령과 데이터이고, 프로세스는 그 프로그램이 실행되면서 생긴 주소 공간, 레지스터 값, 열린 파일 같은 실행 상태를 묶은 운영체제의 관리 단위다.

하나의 프로그램 파일에서 여러 프로세스를 만들 수도 있다. 터미널 두 곳에서 같은 실행 파일을 시작하면 코드는 같지만 PID, 메모리, 레지스터, 열린 파일은 서로 다른 프로세스가 된다.

구분 프로그램 프로세스
성격 저장된 정적 코드와 데이터 실행 중인 동적 상태
위치 파일 시스템 메모리와 커널 자료구조
식별 파일 경로·실행 파일 PID 등 운영체제 식별자
포함 정보 명령, 초기 데이터 주소 공간, 레지스터, 열린 파일, 상태

프로세스를 이루는 machine state

OSTEP은 프로세스를 이해하려면 실행 순간의 machine state를 보라고 설명한다. 핵심은 다음 네 가지다.

주소 공간

프로세스가 접근할 수 있다고 보는 메모리 영역이다. 보통 코드, 전역·정적 데이터, 힙, 스택이 들어간다. 각 프로세스는 자신만의 연속된 주소 공간을 가진 것처럼 보지만, 실제 물리 메모리 배치는 운영체제와 하드웨어가 가상 메모리로 숨긴다.

레지스터

CPU가 현재 계산에 사용하는 작은 저장 공간이다. 특히 프로그램 카운터(PC 또는 instruction pointer)는 다음에 실행할 명령을 가리키고, 스택 포인터는 현재 호출 스택의 위치를 가리킨다. 컨텍스트 스위치 때 이 값들을 보존하지 않으면 중단한 지점에서 실행을 이어 갈 수 없다.

열린 파일

프로세스가 연 파일도 실행 상태의 일부다. 운영체제는 파일 디스크립터와 커널의 열린 파일 정보를 연결해 두고, 프로세스가 읽고 쓰는 대상을 추적한다.

그 밖의 관리 정보

PID, 사용자·그룹 자격, 실행 상태, 스케줄링 정보, 사용한 CPU 시간처럼 커널이 프로세스를 관리하는 데 필요한 값이 더 있다. 구현마다 이름과 배치는 다르지만, 이런 정보를 묶어 흔히 PCB(Process Control Block)라고 설명한다.

실행 파일이 프로세스가 되는 순서

운영체제가 프로그램을 실행할 때의 큰 흐름은 다음과 같다.

  1. 실행 파일의 코드와 정적 데이터를 주소 공간에 배치할 준비를 한다.
  2. 스택을 만들고 인자와 환경 정보를 준비한다.
  3. 힙 등 런타임에 필요한 영역을 초기화한다.
  4. 표준 입력·출력·오류 같은 파일 디스크립터를 설정한다.
  5. CPU 레지스터를 진입점에 맞추고 실행 가능한 상태로 둔다.
  6. 스케줄러가 CPU를 배정하면 첫 명령부터 실행한다.

실제 시스템은 필요할 때 페이지를 읽는 demand paging을 쓰기 때문에 실행 파일 전체를 시작과 동시에 물리 메모리에 복사하는 것은 아니다. 중요한 점은 운영체제가 프로그램에 실행에 필요한 상태를 부여해 프로세스로 관리하기 시작한다는 것이다.

Running·Ready·Blocked 상태

입문 단계에서는 프로세스 상태를 세 가지로 나누면 흐름이 잘 보인다.

Ready --CPU 배정--> Running
Running --선점------> Ready
Running --I/O 요청--> Blocked
Blocked --I/O 완료--> Ready
  • Running: 현재 CPU에서 명령을 실행 중이다.
  • Ready: 실행할 준비는 끝났지만 CPU를 기다린다.
  • Blocked: 디스크·네트워크 같은 사건이 끝나기를 기다려 지금은 실행할 수 없다.

I/O를 요청한 프로세스가 Blocked가 되면 운영체제는 다른 Ready 프로세스를 실행할 수 있다. 덕분에 한 프로세스가 기다리는 동안 CPU 전체가 같이 멈추지 않는다.

운영체제별 실제 상태 이름은 더 세분된다. Linux의 /proc/<pid>/stat에도 running, sleeping, stopped, zombie 등 여러 상태 문자가 나타난다. 세 상태 모델은 모든 구현 세부를 외우기 위한 표가 아니라, 왜 상태 전이가 필요한지 이해하기 위한 출발점이다.

제한된 CPU를 여러 프로세스가 쓰는 방법

CPU가 하나여도 여러 프로그램이 동시에 움직이는 것처럼 보이는 핵심은 time sharing이다. 운영체제는 한 프로세스를 잠시 실행한 뒤 상태를 저장하고 다른 프로세스의 상태를 복원한다. 이 전환이 컨텍스트 스위치다.

여기서 두 층을 분리해야 한다.

  • 메커니즘: 어떻게 실행을 멈추고 다른 상태를 복원할 것인가
  • 정책: 준비된 프로세스 중 무엇을 다음에 실행할 것인가

프로세스 추상화는 관리 대상을 만들고, 제한적 직접 실행은 운영체제가 제어권을 되찾는 메커니즘을 설명한다. FIFO·SJF·RR 같은 선택 기준은 그다음 CPU 스케줄링의 주제다. 이 경계를 나누니 기존 글에서 섞였던 개념이 훨씬 선명해졌다.

프로세스 API가 제공해야 하는 일

구체적인 함수 이름은 운영체제마다 다르지만 프로세스 API에는 대체로 다음 기능이 필요하다.

  • 생성: 새 프로세스를 만든다.
  • 종료: 실행을 끝내거나 강제로 중단한다.
  • 대기: 부모가 자식의 종료를 기다리고 결과를 회수한다.
  • 제어: 우선순위나 실행 조건 같은 속성을 다룬다.
  • 상태 조회: PID, 상태, 자원 사용량 등을 확인한다.

Unix 계열의 fork(), exec(), wait()가 이 역할을 어떻게 나누는지는 OSTEP Process API 정리에서 이어서 볼 수 있다.

직접 확인해 보기

긴 작업 하나를 백그라운드로 실행한 뒤 PID와 상태를 확인하면 추상적인 설명이 실제 커널 인터페이스와 연결된다.

sleep 30 &
pid=$!

ps -o pid,ppid,state,comm -p "$pid"
cat "/proc/$pid/stat" 2>/dev/null | cut -d ' ' -f 1-3
wait "$pid"

/proc은 Linux 인터페이스이므로 macOS에서는 두 번째 명령이 동작하지 않는다. ps 출력의 상태 문자 역시 세 상태 모델과 일대일로 같다고 외우기보다, 각 운영체제 문서를 기준으로 해석해야 한다.

자주 헷갈리는 질문

프로그램과 프로세스는 같은가?

아니다. 프로그램은 실행 전에도 존재하는 파일이고, 프로세스는 실행에 필요한 상태를 가진 인스턴스다.

프로세스가 Blocked면 CPU를 쓰고 있는가?

아니다. 기다리는 사건이 끝날 때까지 실행 대상에서 빠지고, 완료되면 다시 Ready가 된다.

컨텍스트 스위치와 스케줄링은 같은가?

아니다. 스케줄링은 다음 대상을 고르는 정책이고, 컨텍스트 스위치는 실제 실행 대상을 바꾸는 메커니즘이다.

정리

프로세스는 단순히 “실행 중인 프로그램”이라는 문장보다 넓다. 운영체제가 주소 공간, 레지스터, 열린 파일과 관리 정보를 하나로 묶어 실행·중단·재개할 수 있게 만든 추상화다. 이 모델을 먼저 잡아 두면 Process API, 제한적 직접 실행, CPU 스케줄링이 각각 무엇을 설명하는지 헷갈리지 않는다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글