운영체제 용어 사전
프로세스주소 공간

프로세스

실행 중인 프로그램과 그에 딸린 자원의 묶음. 각자 독립된 가상 주소 공간을 갖는다.

실행 중인 프로그램과 그에 딸린 자원의 묶음.

주소 공간의 구조

높은 주소 ┌───────────────┐
          │ 스택          │ 지역 변수 · 함수 호출 프레임 (아래로 자란다)
          ├───────────────┤
          │      ↓        │
          │               │
          │      ↑        │
          ├───────────────┤
          │ 힙            │ 동적 할당 (위로 자란다)
          ├───────────────┤
          │ BSS           │ 초기화 안 된 전역 변수 (0으로 채워진다)
          ├───────────────┤
          │ 데이터        │ 초기화된 전역 변수
          ├───────────────┤
낮은 주소 │ 코드(텍스트)  │ 기계어 (읽기 전용)
          └───────────────┘

이건 가상 주소다. 프로세스마다 자기만의 이 그림을 갖고, 실제 물리 메모리 어디에 있는지는 OS가 관리한다.

PCB — OS가 프로세스에 대해 아는 것

PID · 상태 · 프로그램 카운터 · 레지스터 값 메모리 정보(페이지 테이블 위치) · 열린 파일 목록 · 우선순위 · 부모 PID

컨텍스트 스위치는 결국 '이 PCB 를 저장하고 다른 PCB 를 복원' 하는 일이다

어떻게 태어나나 — fork + exec

pid_t pid = fork();          // 자기 자신을 복제한다
if (pid == 0) {
    execvp("ls", args);      // 자식의 내용을 다른 프로그램으로 갈아 끼운다
} else {
    waitpid(pid, &status, 0);// 부모는 자식을 기다린다
}
  • fork — 주소 공간을 통째로 복제한다 — 실제로는 copy-on-write 로 미룬다

    • 반환값이 둘이다: 부모에게는 자식 PID, 자식에게는 0
  • exec — 현재 프로세스의 내용을 새 프로그램으로 교체한다. PID 는 유지된다

  • 왜 나눴나: fork 와 exec 사이에서 자식만의 준비를 할 수 있다

    • (파일 디스크립터 리다이렉션 · 권한 낮추기 — 셸의 파이프가 이걸로 만들어진다)

좀비와 고아

  • 좀비 — 자식이 끝났는데 부모가 wait 을 안 했다

    • 종료 코드를 담은 PCB 항목이 남는다 → PID 고갈로 이어질 수 있다
  • 고아 — 부모가 먼저 죽었다 → init(PID 1)이 입양해 대신 거둬 준다

  • 컨테이너에서 앱을 PID 1 로 띄우면 좀비를 거둘 주체가 없다

    • tini 같은 최소 init 을 넣거나 --init 을 쓴다

상태

생성 → 준비(ready) ⇄ 실행(running) → 종료
              ↑          ↓
              └── 대기(blocked) ←┘   I/O 를 기다린다

면접 함정

  • "fork는 메모리를 전부 복사한다" → copy-on-write로 미룬다. 쓸 때만 실제 복사가 일어난다.
  • "좀비 프로세스가 메모리를 먹는다" → 메모리는 이미 해제됐다. PID와 PCB 항목만 남는다.

관측

ps -eo pid,ppid,stat,rss,vsz,comm --sort=-rss | head
# STAT  R 실행 · S 대기 · D 중단불가대기(I/O) · Z 좀비 · T 정지
# RSS   실제 물리 메모리 · VSZ 가상 메모리(예약 포함, 훨씬 크다)

pstree -p <pid>            # 부모-자식 관계
cat /proc/<pid>/status     # 상태 · 스레드 수 · 메모리 상세
cat /proc/<pid>/cmdline | tr '\0' ' '

D 상태는 kill -9로도 안 죽는다 — 커널에서 I/O를 기다리는 중이라 시그널을 받을 수 없다. NFS나 디스크 장애에서 흔히 본다.

시그널

  • SIGTERM(15) — "정리하고 종료해" — 잡아서 graceful shutdown 가능 (기본 kill)

  • SIGKILL(9) — "즉시 종료" — 잡을 수 없다. 정리 코드가 안 돈다

  • SIGINT(2) — Ctrl+C

  • SIGHUP(1) — 터미널 종료 — 데몬은 관례적으로 설정 재읽기로 쓴다

  • 컨테이너 종료는 SIGTERM → (grace period) → SIGKILL 순이다

    • 앱이 SIGTERM 을 처리하지 않으면 매번 강제 종료된다 (요청이 잘린다)

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 프로세스 — 주소공간·fork/exec·컨텍스트 스위치