탐색으로 돌아가기
Operating System5 / 24 단계

Process

프로세스

각 프로세스는 자신만의 메모리 공간을 갖고, OS 스케줄러가 CPU 시간을 나눠준다.

프로세스(Process)는 실행 중인 프로그램의 인스턴스로, 디스크에 있는 수동적 파일(program)과 달리 프로그램 카운터·레지스터·스택 같은 실행 상태를 가진 능동적 실체다. 커널은 각 프로세스를 프로세스 제어 블록(PCB, Process Control Block; Linux에서는 task_struct)이라는 자료구조로 표현하며, 여기에 프로세스 상태·PID·CPU 레지스터·스케줄링 정보·메모리 관리 정보·입출력 상태·계정 정보가 저장된다. 각 프로세스는 독립된 가상 주소 공간(address space)을 가지며 이는 text(컴파일된 코드), data(전역·정적 변수), heap(malloc/free로 동적 할당), stack(지역 변수·함수 프레임)의 네 영역으로 구성되고, heap과 stack은 자유 공간의 양 끝에서 서로를 향해 자란다. 프로세스는 new→ready→running→waiting→terminated의 다섯 상태를 오가며, ready에서 running으로는 스케줄러의 dispatch로, running에서 waiting으로는 I/O 요청 등으로, running에서 ready로는 타임 슬라이스 만료(preemption)로 전이한다. Unix에서 새 프로세스는 fork() 시스템 콜로 부모(parent)를 복제해 자식(child)을 만드는데, fork는 자식에게 0을, 부모에게 자식의 PID를 반환하며 현대 커널은 성능을 위해 Copy-on-Write(COW)로 주소 공간 복사를 지연시킨다. 프로세스들은 서로 격리되어 있으므로 협력하려면 파이프·공유 메모리·메시지 큐·소켓·시그널 같은 IPC 메커니즘이 필요하다.

내부 구성

PCB - 프로세스 상태 (Process State)
new/ready/running/waiting/terminated 중 현재 상태를 기록해 스케줄러가 판단하게 한다
PCB - PID / PPID
프로세스와 부모 프로세스를 유일하게 식별하는 정수 식별자다
PCB - CPU 레지스터 & 프로그램 카운터
컨텍스트 스위칭 시 저장/복원되는 실행 문맥(context)으로, 중단 지점을 정확히 재개하게 한다
PCB - 스케줄링 정보
우선순위, 스케줄링 큐 포인터 등 스케줄러가 다음 실행 대상을 고르는 데 쓰는 정보다
PCB - 메모리 관리 정보
페이지 테이블/세그먼트 테이블 포인터(mm_struct)로 가상 주소를 물리 메모리로 매핑한다
PCB - I/O 상태 정보
할당된 장치, 열린 파일 테이블(open file descriptors) 등 입출력 자원을 추적한다
PCB - 계정 정보 (Accounting)
소비한 CPU 시간, 시간 제한, 프로세스 번호 등 사용량 통계를 기록한다
주소 공간 - Text 세그먼트
컴파일된 프로그램 코드가 실행 파일에서 로드되는 읽기 전용 영역이다
주소 공간 - Data 세그먼트
초기화된 전역·정적 변수(및 미초기화 BSS)를 담는 영역으로 main 실행 전에 할당된다
주소 공간 - Heap
malloc/new로 실행 중 동적 할당되는 영역으로 위로 자란다
주소 공간 - Stack
함수 호출 프레임·지역 변수·복귀 주소를 담으며 호출/반환에 따라 자동 관리되고 아래로 자란다
IPC - 파이프 (Pipe)
단방향 바이트 스트림; ordinary pipe는 부모-자식 등 관련 프로세스 간, named pipe(FIFO)는 무관한 프로세스 간 통신에 쓰인다
IPC - 공유 메모리 (Shared Memory)
여러 프로세스가 같은 물리 메모리 영역을 매핑(shmget/shmat)해 시스템 콜 없이 메모리 속도로 통신하는 가장 빠른 방식이다
IPC - 메시지 큐 (Message Queue)
커널이 관리하는 큐에 send/receive로 메시지를 주고받으며 naming·동기화·버퍼링 정책을 가진다
IPC - 소켓 (Socket)
IP:포트로 식별되는 통신 종단점으로 서로 다른 머신 간 통신도 지원한다 (TCP=순서·신뢰 보장, UDP=비연결)
IPC - 시그널 (Signal)
SIGKILL·SIGINT 등 비동기 소프트웨어 인터럽트로 프로세스에 이벤트 발생을 통지한다

핵심 포인트

  • 프로세스 = 실행 중인 프로그램 인스턴스(능동적), 프로그램 = 디스크의 수동적 파일
  • 커널은 각 프로세스를 PCB(task_struct)로 관리하며 상태·PID·레지스터·메모리·I/O 정보를 담는다
  • 주소 공간은 text/data/heap/stack 4영역이며 heap과 stack이 서로를 향해 자란다
  • 5가지 상태: new → ready → running → waiting → terminated (dispatch, preemption, I/O로 전이)
  • fork()는 부모를 복제해 자식 생성, 자식엔 0·부모엔 자식 PID 반환, COW로 복사 지연
  • 프로세스는 서로 격리되어 있어 협력하려면 IPC가 필수다
  • 컨텍스트 스위칭 시 PCB에 현재 상태를 저장하고 다음 프로세스 상태를 복원한다

심화

면접 단골 질문은 'fork() 직후 부모와 자식이 공유하는 것과 복제되는 것'이다. Copy-on-Write 덕분에 fork 직후 부모와 자식은 물리 페이지를 공유하지만, 어느 한쪽이 쓰기를 시도하는 순간 해당 페이지만 복제된다. 또 fork() 후 exec()를 호출하면 자식의 주소 공간이 새 프로그램으로 완전히 교체되므로, 사실 fork로 복사한 페이지 대부분이 버려진다는 점(그래서 vfork·posix_spawn이 존재)까지 알면 좋다. 파일 디스크립터는 fork 시 복제되어 부모와 자식이 같은 파일 오프셋을 공유하는데, 이것이 쉘 파이프라인 구현의 핵심이다. 또 하나 자주 나오는 개념이 '좀비(zombie)'와 '고아(orphan)' 프로세스다. 자식이 종료되었지만 부모가 wait()로 종료 상태를 회수하지 않으면 PCB가 남아 좀비가 되고, 반대로 부모가 먼저 죽으면 자식은 고아가 되어 init(PID 1)이 입양해 정리한다. IPC 선택 기준도 중요한데, 공유 메모리는 가장 빠르지만 동기화(세마포어 등)를 직접 해야 하고, 메시지 큐·파이프는 커널이 동기화를 대신 해주지만 복사 비용이 있으며, 소켓만이 네트워크 경계를 넘을 수 있다는 트레이드오프를 설명할 수 있어야 한다.

쉽게 말하면 아파트의 각 세대(프로세스)는 독립된 공간을 갖고, 문을 통해서만(IPC) 소통.

면접 예상 질문

#프로세스#스케줄링#가상 메모리#격리#IPC