프로세스는 운영체제가 실행 중인 프로그램을 다루는 가장 기본적인 단위이다. 이 개념을 제대로 이해하지 못하면 CPU 사용량, 메모리 관리, 스케줄링 등 시스템의 작동 원리를 명확히 알 수 없다. 또한, 리눅스와 같은 유닉스 계열 운영체제에서 동작 중인 프로세스들을 관찰하고 문제를 진단하려면 프로세스 상태와 그 전이에 대한 이해는 필수적이다. 이 글에서는 프로세스의 정의부터 상태 전이 모델, 그리고 실무에서 마주치는 각 상태의 의미까지 단계적으로 설명한다.
목차
1. 프로세스란 무엇인가?
운영체제에서 프로세스(Process)는 실행 중인 프로그램을 의미한다. 단순히 디스크에 저장된 실행 파일이 아니라, 메모리 상에 적재되어 CPU에서 실제로 명령어가 수행되는 동적인 실행 단위이다. 운영체제는 이 프로세스를 관리하면서 CPU 자원, 메모리, I/O를 효율적으로 스케줄링하고 보호한다.
● 프로세스의 정의와 구성 요소
하나의 프로세스는 다음과 같은 주요 요소들로 구성되어 있다.
구성 요소 | 설명 |
텍스트(Text) 섹션 | 실행할 코드 (명령어) |
데이터(Data) 섹션 | 전역 변수, 정적 변수 |
힙(Heap) | 동적 할당 메모리 (malloc 등) |
스택(Stack) | 함수 호출 정보, 지역 변수 |
레지스터 상태 | 프로그램 카운터, 스택 포인터 등 |
PCB(Process Control Block) | 운영체제가 해당 프로세스를 식별하고 제어하기 위해 사용하는 메타데이터 |
아래 그림은 일반적인 프로세스 메모리 구조를 도식화한 것이다.
주소 증가 방향 →
──────────────────────────────────────────>
+-------------------+ 낮은 주소
| Text Section |
+-------------------+
| Data Section |
+-------------------+
| BSS Section |
+-------------------+
| Heap |← 위로 증가
| ↑ |
| | |
+-------------------+ ← 비어있는 공간 (MMAP 영역 등)
| Stack |← 아래로 감소
+-------------------+ 높은 주소
Stack은 높은 주소에서 시작하여 낮은 주소로 , Heap은 낮은 주소에서 시작하여 높은 주소로 증가한다. 주소 증가 방향은 Text 이 구조는 Text → Data → Heap → (Stack 아래에서 시작)이다. 실제로 ps, top, cat /proc/[pid]/maps 등의 명령어를 통해 확인할 수 있다.
● 프로세스는 왜 중요한가?
- 시스템 자원의 단위: 프로세스는 CPU 시간, 메모리, 파일 핸들, 입출력 등 모든 자원의 기본 단위이다.
- 격리된 실행 환경: 각 프로세스는 독립된 주소 공간을 가지므로, 다른 프로세스의 메모리에 접근할 수 없다. 이는 보안과 안정성의 핵심이다.
- 스케줄링 단위: 운영체제의 스케줄러는 각 프로세스를 기준으로 CPU를 배정한다.
따라서 프로세스의 개념을 이해하는 것은 단순히 운영체제를 배우는 것이 아니라, 시스템 전체의 동작 원리를 체계적으로 이해하는 출발점이다.
2. 프로그램과 프로세스의 차이
많은 개발자들이 ‘프로그램’과 ‘프로세스’를 혼동한다. 둘은 표면적으로 유사하지만, 정적(Static) vs 동적(Dynamic), 파일(Data) vs 실행 인스턴스(Execution)라는 근본적인 차이를 가진다.
구분 | 프로그램 | 프로세스 |
정의 | 실행 가능한 명령어 집합 | 실행 중인 프로그램 인스턴스 |
존재 위치 | 디스크 | 메모리 |
상태 | 정적 (파일 상태) | 동적 (실행 상태) |
복수 실행 가능 여부 | 하나의 프로그램은 여러 프로세스로 실행 가능 | 각 프로세스는 독립된 자원 및 상태 보유 |
예시 | /usr/bin/python3 | python3 script.py 실행 시 생성되는 실행 인스턴스 |
예를 들어, 사용자가 웹 브라우저를 두 개 실행하면 프로그램은 하나지만 프로세스는 둘이다. 각각은 메모리, CPU 점유 상황, 자식 스레드 개수 등이 완전히 다를 수 있으며, 서로 간섭할 수 없다. 이 차이를 명확히 이해하는 것은 디버깅, 성능 튜닝, 보안 분석 등에서 중요한 기초가 된다. 특히 컨테이너나 샌드박싱 환경에서 ‘이미지’와 ‘실행 컨테이너’의 관계 또한 이 개념의 확장선상에 있다.
3. 프로세스 상태의 종류
운영체제는 다수의 프로세스를 동시에 관리한다. 하지만 CPU는 한 시점에 하나의 프로세스만 실행할 수 있기 때문에, OS는 각 프로세스가 어떤 상태(State)에 있는지를 추적하고 제어한다.
● 대표적인 프로세스 상태 5가지
상태 | 설명 |
New | 프로세스가 생성 중이며 아직 메모리에 적재되지 않음 |
Ready | 실행 준비 완료, CPU 할당 대기 중 |
Running | CPU를 할당받아 실제 명령어 수행 중 |
Waiting (Blocked) | I/O나 이벤트 발생을 대기 중 |
Terminated | 실행이 완료되어 종료된 상태 |
다음 그림은 프로세스 상태 전이 모델을 간단히 도식화한 것이다:
+-------+
| New |
+---+---+
|
v
+-------+ Timer Expire +---------+
| Ready |<-------------------------| Running |
+---+---+------------------------> +----+----+
^ I/O 완료 | |
| | v
| +---+----+ Process Exit
+---------------| Waiting|<----------+
+--------+ |
^ |
| |
I/O 요청 Kill Signal
※ 선점형 스케줄링이 적용되는 시스템에서는 ‘Running → Ready’ 전이가 타이머에 의해 자주 발생하며, 멀티태스킹 성능에 결정적 영향을 준다.
● 선택적으로 존재하는 상태
일부 시스템에서는 다음 상태들도 사용된다:
- Suspended: 메모리에서 내려간 대기 상태 (Swap-out)
- Zombie: 종료됐지만 부모 프로세스가 wait()으로 수거하지 않은 상태
- Stopped: 신호(Signal)에 의해 일시 중지된 상태 (SIGSTOP, SIGTSTP 등)
이러한 상태들은 실무에서 문제 해결 시 매우 중요하다. 예를 들어 좀비(Zombie)는 잘못된 자식 프로세스 관리로 인해 시스템에 리소스 누수를 초래할 수 있다.
4. 프로세스 상태 전이 (Process State Transitions)
운영체제는 다수의 프로세스를 효율적으로 관리하기 위해 각 프로세스의 상태를 추적하고, 상태 간 전이를 엄격하게 정의한다. 이러한 상태 전이 모델은 단순한 흐름도가 아니라, CPU 자원 스케줄링, 입출력 처리, 메모리 관리, 시스템 콜 처리 전반에 걸친 운영체제의 핵심 메커니즘을 반영한다. 이 절에서는 프로세스의 주요 상태와 상태 간 전이 조건을 명확하게 설명한다.
1. 기본 프로세스 상태
운영체제는 일반적으로 다음과 같은 기본적인 다섯 가지 상태를 정의한다:
- New (생성): 프로세스가 막 생성되어 운영체제가 이를 등록하는 중인 상태. 아직 Ready 큐에는 들어가지 않았다.
- Ready (준비): 실행에 필요한 메모리, PCB(Process Control Block) 등 자원이 할당된 후, CPU 할당을 기다리는 상태.
- Running (실행): 현재 CPU를 점유하고 있으며, 사용자 코드 혹은 커널 코드가 실제로 실행 중인 상태.
- Waiting / Blocked (대기): 디스크 I/O, 네트워크, 타이머 인터럽트 등 외부 이벤트를 기다리며 CPU를 사용하지 않는 상태.
- Terminated (종료): 프로세스가 정상 종료 또는 예외 상황으로 종료되어 운영체제가 해당 PCB와 자원을 회수 중인 상태.
2. 상태 전이와 조건
상태 간 전이는 일관된 조건에 따라 발생하며, 각각의 전이 이벤트는 커널 수준에서 처리된다. 대표적인 전이 흐름과 조건은 다음과 같다:
- New → Ready: 운영체제가 프로세스를 생성(admit)하고 Ready 큐에 등록. fork() 이후 exec 전 또는 프로세스 생성 직후.
- Ready → Running: 스케줄러가 해당 프로세스에 CPU를 할당(dispatch).
- Running → Waiting: 프로세스가 I/O 요청 또는 특정 이벤트를 기다리기 위해 자발적으로 CPU를 반납. 예: read(), sleep().
- Waiting → Ready: 대기 중이던 이벤트(I/O 완료 등)가 발생해 Ready 큐로 복귀. 인터럽트 기반 처리.
- Running → Ready: 타이머 인터럽트 등으로 인한 시간 할당량 소진. 선점형 스케줄링 환경에서만 해당.
- Running → Terminated: exit() 호출 또는 예외 처리(SIGSEGV, SIGKILL 등)로 인해 종료 요청.
- Any → Terminated: 외부 신호나 시스템 종료 등으로 인한 강제 종료. 예: kill -9 [pid].
3. 확장 상태 (일부 운영체제에서 사용)
일부 고급 운영체제에서는 다음과 같은 상태를 추가로 도입해 메모리 자원 최적화를 시도한다:
- Suspended Ready: Ready 상태였지만 물리 메모리가 부족해 디스크로 스와핑된 상태.
- Suspended Blocked: Waiting 상태였지만 동일하게 메모리에서 내려진 상태. 이벤트 완료 후에도 즉시 실행될 수 없음.
이러한 상태는 메모리 압력 상황에서 프로세스를 유지하면서도 자원을 확보하는 데 유리하지만, 스케줄러의 복잡도가 증가한다.
4. 상태 전이의 실질적 의미
- Ready ↔ Running 전이는 스케줄링의 핵심이며, 성능과 응답성에 직접적인 영향을 준다.
- Running → Waiting → Ready의 흐름은 비동기 I/O와 CPU 병렬 사용을 실현하는 구조적 기반이다.
- Running → Terminated 전이는 자원 회수와 관련되어 있어 운영체제의 안정성에 직접적으로 연결된다.
이러한 전이 과정은 단순한 상태 이동이 아닌, 커널의 자원 할당 정책, 스케줄링 알고리즘, 인터럽트 및 신호 처리 모델과 밀접히 연관된다.
5. 상태 전이 모델의 실무 활용
운영체제에서 상태를 실시간으로 추적하고 분석하는 것은 시스템 튜닝과 병목 현상 제거에 필수적이다.
명령어 / 경로 | 설명 |
ps -o pid,stat,cmd | 프로세스 상태 확인 (R: Running, S: Sleep, Z: Zombie 등) |
top, htop | 실시간 상태 변화 모니터링 |
/proc/[pid]/status | 각 프로세스의 세부 상태, 대기 사유, context switch 횟수 등 |
strace, perf trace | 프로세스가 어떤 시스템 콜에서 블록되는지 추적 가능 |
kill -s | 상태 전이를 직접 유도 (SIGSTOP → Waiting, SIGCONT → Ready 등) |
6. 정리
- 프로세스는 New → Ready → Running → Waiting/Terminated 형태의 유한 상태 기계(FSM, Finite State Machine)로 모델링된다.
- 상태 전이는 시스템 콜, 인터럽트, 시그널, 스케줄러 결정에 의해 유기적으로 발생한다.
- 상태 전이 모델을 정확히 이해하면 시스템 동작의 이면을 파악하고, 병목 해소, 안정성 확보, 튜닝에 활용할 수 있다.
이와 같이 프로세스 상태 전이의 정확한 이해는 단순한 이론 학습을 넘어, 시스템 문제 진단 및 커널 레벨 프로그래밍까지 확장 가능한 핵심 지식이다.
5. PCB와 콘텍스트 스위칭의 역할
운영체제가 멀티태스킹을 수행하려면 수많은 프로세스의 상태를 정밀하게 추적하고, 필요에 따라 이들을 빠르고 정확하게 전환할 수 있어야 한다. 이 핵심 기능을 가능하게 하는 두 축이 바로 PCB (Process Control Block)와 Context Switching (문맥 교환)이다.
1. PCB(Process Control Block): 프로세스의 설계도
PCB는 각 프로세스의 “정체성”과 “실행 맥락”을 저장하는 커널 데이터 구조로, 운영체제가 프로세스를 제어하고 상태를 유지하는 데 필수적이다. 주요 구성항목은 다음과 같다.
항목 | 설명 |
PID | 프로세스 식별자 (Process ID) |
Program Counter | 다음 실행할 명령어의 주소 |
CPU 레지스터 값 | 실행 중이던 모든 레지스터 저장 |
프로세스 상태 | Ready, Running, Waiting 등 현재 상태 |
우선순위 | 스케줄링 시 우선순위 정보 |
메모리 맵 정보 | 코드, 데이터, 스택 등 세그먼트 위치 |
파일 디스크립터 | 열려 있는 파일 목록 및 입출력 정보 |
시그널 핸들러 | 수신 시그널 및 처리 함수 |
PCB는 커널 내부에 저장되며, 일반 유저는 접근할 수 없다. 하지만 /proc/[pid]/status 등을 통해 일부 정보를 확인할 수 있다.
2. 컨텍스트 스위칭(Context Switching): 실행 흐름의 전환
Context Switching은 CPU가 현재 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태를 복원하는 작업이다. 이로 인해 하나의 CPU로도 여러 프로세스가 “동시에 실행되는 것처럼” 보이게 만든다.
핵심 단계:
- 현재 프로세스의 레지스터, PC, 상태 등을 PCB에 저장
- 다음 실행할 프로세스의 PCB를 조회
- 그 PCB에 저장된 정보로 CPU 상태 복원
- 프로세스 전환 완료
이 과정은 커널 모드에서 작동하며, 일반적으로 타이머 인터럽트, 시스템 콜, I/O 완료 등의 이벤트에 의해 트리거된다.
오버헤드 이슈
문맥 교환은 비용이 크다. 특히 다음 상황에서 문제로 작용할 수 있다:
- 높은 빈도의 컨텍스트 스위칭 → CPU 캐시 손실 증가
- IO-bound 프로세스가 많을 때 불필요한 상태 저장/복원
- 멀티코어 간 CPU 간 이동(MIGRATION) 시 PCB 동기화 비용 증가
3. PCB와 컨텍스트 스위칭의 관계
- PCB는 컨텍스트 스위칭을 성공적으로 수행하기 위한 기반 데이터 구조다.
- CPU가 프로세스를 교체할 때, PCB는 정확한 상태 저장소이자 재개 지점 역할을 수행한다.
- 스레드 기반 시스템에서는 **TCB(Thread Control Block)**를 사용하지만, 기본 구조는 PCB와 유사하다.
4. 실무 활용: PCB/Context Switching 확인 명령어
명령어 / 경로 | 용도 |
cat /proc/[pid]/status | PCB 일부 정보 확인 (PID, 상태, context switch 횟수 등) |
top, htop | context switch 빈도, 실행 상태 실시간 확인 |
vmstat -s | 시스템 전반의 context switch 누적 횟수 |
pidstat -w [pid] | 특정 프로세스의 context switch 통계 확인 |
perf stat -e cs | 커널 레벨에서의 문맥 교환 분석 |
5. 정리
- PCB는 각 프로세스의 핵심 상태 정보를 저장하는 운영체제의 내부 구조이며, 모든 스케줄링, 종료, 상태 복원 작업의 기반이 된다.
- Context Switching은 이러한 PCB 정보를 기반으로 프로세스 실행 흐름을 유기적으로 전환하는 실행 제어 기술이다.
- 시스템 최적화에서는 불필요한 문맥 교환을 최소화하고, PCB 관리를 효율적으로 유지하는 것이 중요하다.
이처럼 PCB와 컨텍스트 스위칭은 운영체제의 실질적인 ‘두뇌’ 역할을 하며, 모든 다중 작업 환경의 기반이 된다. 이 둘의 동작 원리와 성능 영향을 정확히 이해하는 것은 시스템 엔지니어, 커널 개발자, 인프라 최적화 담당자에게 필수적인 지식이다.
6. 상태 전이와 CPU 스케줄링
운영체제는 수십~수천 개의 프로세스 중 어떤 것을 CPU에 할당할지 결정해야 한다. 이 과정을 CPU 스케줄링(CPU Scheduling)이라 하며, 상태 전이와 밀접하게 연결된다. 프로세스가 Ready → Running으로 전이될 수 있도록 스케줄러가 결정하는 것이다.
● 스케줄러의 주요 목적
- 공정성(Fairness): 모든 프로세스가 적절한 CPU 기회를 가짐
- 효율성(Efficiency): CPU idle 시간 최소화
- 응답 시간(Response Time): 대화형 시스템에서 빠른 반응
- 처리량(Throughput): 단위 시간당 완료된 프로세스 수 최대화
● 주요 스케줄링 알고리즘과 상태 전이 관계
알고리즘 | 상태 전이 시 특징 |
FCFS (First-Come, First-Served) | Ready 큐에서 먼저 들어온 프로세스 우선 |
SJF (Shortest Job First) | 실행 시간이 짧은 Ready 프로세스를 우선 실행 |
RR (Round Robin) | 각 프로세스에 일정 시간(CPU quantum)만 부여 후 선점 → Running → Ready |
Priority Scheduling | 우선순위 높은 Ready 프로세스를 먼저 선택 |
선점형 스케줄링의 경우, 타이머 인터럽트가 발생하면 커널은 현재 프로세스를 강제로 중단시켜 다른 프로세스로 콘텍스트 스위칭을 수행한다. 이때 Running → Ready 전이가 핵심이다. 스케줄링은 나중에 구체적으로 다룰 예정이다.
● 실시간 시스템의 스케줄링
실시간 시스템(RTOS)이나 우선순위 기반 시스템에서는 특정 상태 전이가 무시되거나, 강제로 우선순위가 낮은 프로세스를 중단시키기도 한다. 예로는 SCHED_FIFO, SCHED_RR 등 리눅스 실시간 정책을 들 수 있다.
7. 리눅스에서 프로세스 상태 확인하기
리눅스는 /proc 가상 파일 시스템을 통해 각 프로세스의 상태를 상세하게 보여준다. 이 정보는 디버깅, 성능 분석, 보안 대응 등 실무에서 매우 유용하다.
● ps 명령어로 상태 확인
$ ps -eo pid,ppid,state,cmd
필드 | 설명 |
PID | 프로세스 ID |
PPID | 부모 프로세스 ID |
STATE | 현재 상태 (S, R, D, T, Z 등) |
CMD | 실행 중인 명령어 |
상태 코드 예시:
코드 | 의미 |
R | Running |
S | Sleeping (interruptible wait) |
D | Uninterruptible sleep (예: I/O 대기) |
T | Stopped (일시 중지됨) |
Z | Zombie |
● /proc/[pid]/status 확인
$ cat /proc/1234/status
부분 출력 예시:
Name: nginx
State: S (sleeping)
Pid: 1234
PPid: 1
Threads: 5
VmRSS: 15248 kB
해당 파일에는 상태뿐 아니라 메모리 사용량, 스레드 개수, UID 등도 포함되어 있어 리소스 관리에 중요하다.
● 실시간 상태 추적: top, htop
- top: 리눅스 표준 유틸리티, 실시간 CPU/메모리 사용량 표시
- htop: 시각화 및 인터랙티브 지원, 상태 필터링 및 정렬 기능 우수
$ top
출력 예시:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2345 root 20 0 213248 11632 8652 S 0.3 0.1 0:00.42 sshd
2378 user 20 0 140012 8924 7632 R 4.0 0.3 0:12.98 python
여기서 S는 sleeping, R은 running 상태를 의미한다. 프로세스의 상태 변화가 실시간으로 반영되므로, 병목 분석, 좀비 프로세스 탐지, 부하 프로세싱 확인 등에 매우 유용하다.
8. 요약
프로세스는 실행단위로서 운영체제의 스케줄링, 자원 관리, 보안, 병목 분석 등 모든 시스템 동작의 출발점이다. 이번 글에서 다음과 같은 내용을 다루었다.
- 프로세스는 실행 중인 프로그램이며, 메모리 공간과 PCB로 관리된다.
- 프로그램과 프로세스는 정적/동적이라는 본질적인 차이가 있다.
- 운영체제는 프로세스를 여러 상태(New, Ready, Running, Waiting, Terminated)로 구분하여 관리하며, 이 상태들은 이벤트와 스케줄링에 따라 전이된다.
- PCB는 모든 프로세스 정보를 저장하는 핵심 자료구조이며, 문맥 전환 시 이 정보가 핵심 역할을 한다.
- CPU 스케줄러는 프로세스 상태 전이에 직접 관여하며, 알고리즘에 따라 효율성과 성능에 큰 차이를 만든다.
- 리눅스에서는 /proc, ps, top 등을 통해 실시간으로 프로세스 상태를 추적하고 문제를 분석할 수 있다.
운영체제나 시스템 프로그램을 설계하거나, 단순한 성능 분석 이상의 문제 해결을 위해서는 프로세스 개념을 “암기”가 아닌 “이해”하는 것이 선결 조건이다. 프로세스를 알면 시스템의 본질이 보인다.