운영체제 따라잡기

가상 메모리

meellon 2026. 7. 1. 05:00

학습 목표

가상 메모리가 물리 RAM보다 큰 주소 공간·여러 프로세스를 어떻게 지원하는지 설명할 수 있다.

요구 페이징(demand paging) 에서 페이지를 접근 시점에 올리는 이유를 설명할 수 있다.

페이지 폴트 발생 조건과 OS 폴트 핸들러 처리 단계를 설명할 수 있다.

FIFO·Optimal·LRU·Clock 교체 알고리즘의 아이디어와 한계를 비교할 수 있다.

문제 상황

  • 서버 RAM 16GB인데 Java heap -Xmx32g어떻게 돌아가나?
    • 전부 RAM에 있지 않음, 스왑·요구 페이징
  • 처음 malloc(1GB) 했을 때 물리 메모리가 바로 1GB 안 늘어난다
    • lazy allocation, PTE valid=0
  • 디스크 I/O가 갑자기 늘고 CPU는 idle에 가깝다
    • 페이지 폴트 폭주·스래싱 직전 신호
  • OOMKilled — 커널이 프레임 부족을 더 이상 버티지 못함

페이징·TLB를 봤다. 이번엔 디스크까지 포함한 주소 공간 환상프레임이 모자랄 때다.

1. 가상 메모리 개념

각 프로세스는 자기만의 가상 주소 공간을 본다. 물리 RAM은 공유 풀이고, 일부 페이지는 스왑(swap) 영역(디스크)에 둔다.

구분 설명
가상 주소 공간 프로세스 관점 — 코드·힙·스택·mmap
물리 프레임 실제 DRAM 조각 — 한정된 자원
스왑 공간 디스크에 둔 페이지 백업 — RAM보다 훨씬 클 수 있음
PTE valid=0 페이지가 RAM에 없음 — 디스크에 있거나 아직 미할당
  • 메모리 오버커밋: 가상 합이 물리+스왑을 넘을 수 있음 — 실제 접근 시 OOM
  • 격리: 프로세스 A의 가상 주소 0x1000과 B의 0x1000은 다른 물리 프레임
  • 공유: 같은 물리 프레임을 여러 PTE가 가리킬 수 있음 (코드, shm)

2. 요구 페이징 (Demand Paging)

미리 프로세스 전체를 RAM에 올리지 않는다. 참조할 때 페이지를 읽어 온다.

단계 동작
exec / fork 페이지 테이블·mmap만 준비, 많은 PTE는 valid=0
첫 접근 페이지 폴트 → 디스크에서 프레임으로 로드
이후 접근 PTE valid=1, 일반 페이징
  • 순수 요구 페이징: swap 없이 처음 로드만 (실행 파일 backing store)
  • 스왑 포함: RAM에서 내쳤다가 다시 접근하면 디스크에서 재로드
  • malloc 대용량: 예약만 하고 physical page는 touch할 때 할당 (OS·런타임마다 다름)
  • COW(copy-on-write): fork 직후 쓰기 전까지 부모 프레임 공유 — 쓰기 시 폴트로 복사

3. 페이지 폴트 (Page Fault)

CPU가 논리 주소에 접근했는데 PTE가 valid=0 이거나 보호 위반이면 페이지 폴트 트랩이 난다.

일반적인 폴트 처리 (major fault):

  1. 하드웨어: MMU가 폴트 → CPU가 커널 모드로 전환, 폴트 주소·원인 저장
  2. OS 핸들러: 폴트가 합법적인지 확인 (스택 확장, COW, lazy alloc 등)
  3. 프레임 확보: 빈 프레임이 없으면 교체 알고리즘으로 victim 선택
  4. 디스크 I/O: 스왑 또는 파일에서 페이지 읽기 (major fault — 느림)
  5. PTE 갱신: frame#, valid=1, protection 설정
  6. 재실행: fault 난 명령부터 다시 — 이번엔 TLB miss 후 정상 접근
폴트 종류
minor 이미 RAM에 있는데 TLB만 비어 있음
major 디스크에서 페이지 읽어야 함
illegal NULL·권한 위반 → SIGSEGV
  • minflt / majflt (time -v, /proc/[pid]/stat)로 관측
  • double page fault 등 재진입 케이스는 핸들러가 프레임·스택을 미리 확보해야 함

4. 페이지 교체 알고리즘

물리 프레임이 꽉 찼을 때 victim 페이지를 골라 RAM에서 내치고(스왑 또는 버림), 새 페이지를 올린다.

알고리즘 아이디어 장점 한계
FIFO 가장 먼저 들어온 프레임 교체 구현 단순(큐) Belady: 프레임 늘려도 폴트 증가 가능
Optimal 가장 먼지 쓸 페이지 교체 폴트 수 이론적 최소 미래 참조 알 수 없음 — 벤치마크용
LRU 가장 오래 쓴 페이지 교체 지역성 반영 정확 LRU는 비용 큼 → 근사 LRU
Clock reference bit 원형 스캔 LRU 근사, 구현 실용적 한 바퀴만으로는 불완전

예시 (프레임 3개, 참조 순서 1,2,3,4,1,2,5,1,2,3,4,5):

알고리즘 페이지 폴트 수 (대표값)
FIFO 9
LRU 5
Optimal 5

  • Clock: 손가락이 프레임을 돌며 reference bit=1이면 0으로 내리고, 0이면 victim
  • Linux 등은 LRU 근사(active/inactive list, aging) + dirty 페이지는 쓰기 비용 고려
  • working set·스래싱은 다음 편에서

5. 스왑과 성능

항목 설명
스왑 아웃 victim 페이지를 디스크에 쓰고 PTE valid=0
스왑 인 폴트 시 디스크에서 프레임으로 읽기
thrashing 폴트만 반복, 유용한 작업 거의 없음 — working set > RAM
swappiness Linux가 얼마나 공격적으로 파일 캐시 대신 스왑 쓸지 (0~100)
  • SSD 스왑은 HDD보다 낫지만 RAM 접근 대비 여전히 느림
  • 컨테이너·DB는 스왑 끄기도 흔함 — 지연 예측 가능성
  • OOM killer: 스왑으로도 못 버티면 프로세스 강제 종료

6. 정리

  • 가상 메모리 = 큰 가상 공간 + 제한된 프레임 + 스왑
  • 요구 페이징으로 필요한 페이지만 로드, 페이지 폴트가 로드·교체 트리거
  • 교체는 FIFO·LRU·Clock 등 — 실무는 LRU 근사 + dirty/reference 고려
  • 다음: 세그멘테이션, working set, 스래싱 완화

다음에 다룰 것

  • 세그멘테이션과 군집화
  • working set, 스래싱

해당 내용은 Operating System Concepts, 10/E (Avraham Silberschatz, Peter Baer Galvin, Greg Gagne) 의 내용을 기반으로 합니다.

'운영체제 따라잡기' 카테고리의 다른 글

파일 시스템 개념  (0) 2026.07.03
세그멘테이션과 군집화  (0) 2026.07.02
페이징  (0) 2026.06.30
메모리 관리 기초  (0) 2026.06.29
동시성 문제 사례  (0) 2026.06.28