페이지 폴트

프로세스가 접근하려는 가상 메모리 페이지가 물리 메모리에 존재하지 않을 때 발생하는 Fault 유형의 예외(벡터 14)입니다.

왜 발생하는가?

운영체제는 가상 메모리 기법을 사용하여 실제 물리 메모리보다 큰 주소 공간을 프로세스에 제공합니다. 모든 페이지를 물리 메모리에 올려두지 않고, 필요한 시점에 로드하는 요구 페이징(Demand Paging) 방식을 사용하기 때문에 페이지 폴트가 발생합니다.

페이지 폴트 처리 흐름

① 프로세스가 가상 주소 접근
② MMU가 페이지 테이블 조회
③ Valid Bit = 0 → 물리 메모리에 없음
④ Page Fault 예외 발생 (벡터 14)
⑤ CPU → IDT[14] → 페이지 폴트 핸들러 진입 (커널 모드)
⑥ 커널이 원인 분석
    ├── 유효한 접근 → 디스크에서 페이지 로드
    └── 잘못된 접근 → 프로세스 종료 (Segmentation Fault)
⑦ 빈 프레임 확보 (없으면 페이지 교체 알고리즘 실행)
⑧ 디스크 → 물리 메모리로 페이지 복사
⑨ 페이지 테이블 갱신 (Valid Bit = 1, 프레임 번호 기록)
⑩ 원래 명령어 재실행 (Fault이므로 같은 명령어로 복귀)

** MMU

프로세스: arr[1000] 접근
    │
    ▼
 MMU: 페이지 테이블 조회 → Valid Bit = 0
    │
    ▼
 Page Fault 발생 → 커널 모드 전환
    │
    ├── 유효한 접근?
    │    ├── Yes → 디스크에서 페이지 로드 → 테이블 갱신 → 재실행
    │    └── No  → SIGSEGV → 프로세스 종료
    │
    ▼
 arr[1000] 재실행 → 성공

페이지 테이블 엔트리 구조

┌─────────────────────────────────────────────┐
│ 프레임 번호 │ Valid │ Dirty │ Reference │ 권한(R/W/X) │
└─────────────────────────────────────────────┘
비트설명
Valid1: 물리 메모리에 존재 / 0: 부재 → 페이지 폴트
Dirty1: 페이지가 수정됨 → 교체 시 디스크에 기록 필요
Reference1: 최근 참조됨 → 페이지 교체 알고리즘에서 활용
권한읽기/쓰기/실행 권한 → 위반 시 Protection Fault

페이지 폴트의 종류

종류설명처리
Minor (Soft)페이지가 이미 메모리에 있지만 매핑만 안 된 경우페이지 테이블만 갱신 (빠름)
Major (Hard)페이지가 디스크에만 존재, 물리 메모리에 없음디스크 I/O 필요 (느림)
Invalid존재하지 않는 주소 접근 (잘못된 접근)프로세스 종료 (Segfault)
페이지 폴트
  │
  ├── Minor Fault ── 메모리에 있음, 매핑만 필요 ── ~수 μs
  │    ex) 공유 라이브러리가 이미 다른 프로세스에 의해 로드됨
  │
  ├── Major Fault ── 디스크에서 로드 필요 ──────── ~수 ms
  │    ex) 최초 접근, 스왑 아웃된 페이지
  │
  └── Invalid ────── 잘못된 주소 접근 ──────────── 프로세스 종료
       ex) NULL 포인터, 할당되지 않은 영역

빈 프레임이 없을 때 — 페이지 교체 알고리즘

알고리즘설명특징
FIFO가장 먼저 들어온 페이지 교체단순하지만 Belady's Anomaly 발생 가능
LRU가장 오래 사용되지 않은 페이지 교체성능 우수, 구현 비용 높음
LFU사용 빈도가 가장 낮은 페이지 교체최근 로드된 페이지에 불리
Clock (Second Chance)Reference Bit 활용, FIFO 개선LRU 근사, 실제 OS에서 많이 사용
OPT미래에 가장 늦게 사용될 페이지 교체이론적 최적해, 실제 구현 불가
[Clock 알고리즘 예시]

         ──→ [A, ref=1] → [B, ref=0] → [C, ref=1] → [D, ref=0]
  포인터 ─┘

  교체 필요 시:
  ① A(ref=1) → ref=0으로 변경, 넘어감
  ② B(ref=0) → 교체 대상! B를 내보내고 새 페이지 로드

스레싱 (Thrashing)

페이지 폴트가 과도하게 발생하여 CPU가 실제 작업보다 페이지 교체에 대부분의 시간을 소비하는 현상입니다.

항목내용
원인물리 메모리 부족, 너무 많은 프로세스 동시 실행
증상CPU 사용률 급락, 디스크 I/O 급증
해결프로세스 수 줄이기, 메모리 증설, Working Set 모델 적용
정상 상태: CPU 사용률 ↑, 페이지 폴트 적음
    │
    ▼  프로세스 계속 추가
    │
스레싱: CPU 사용률 ↓↓, 디스크 I/O ↑↑
    → 페이지 로드 → 다른 페이지 교체 → 또 폴트 → 무한 반복

Java에서의 페이지 폴트

// 1. 큰 배열 할당 — 가상 메모리만 확보, 실제 물리 메모리 할당은 접근 시
byte[] huge = new byte[100 * 1024 * 1024]; // 100MB 가상 메모리 확보

huge[0] = 1;             // 첫 페이지 접근 → Major Page Fault
huge[4096] = 1;          // 다음 페이지 접근 → Major Page Fault
huge[50_000_000] = 1;    // 또 다른 페이지 → Major Page Fault

// 2. 메모리 매핑 파일 — 파일 내용을 접근할 때마다 페이지 폴트 발생 가능
FileChannel fc = FileChannel.open(Path.of("large.dat"));
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
byte b = mbb.get(0);           // 해당 오프셋 페이지가 없으면 Page Fault
byte b2 = mbb.get(1_000_000);  // 다른 위치 접근 시 또 Page Fault 가능

// 3. 클래스 로딩 — JVM이 .class 파일을 메모리에 로드할 때
Class<?> clazz = Class.forName("com.example.MyClass");
// 해당 클래스 파일이 메모리에 없으면 Page Fault → 디스크에서 로드

CSLOG에서 보기