
구조

TLB는 최근에 접근한 page → frame 매핑을 캐싱하는 mmu에 위치한 하드웨어(SRAM)이다.
Page table은 DRAM에 존재한다. 따라서 메모리 접근 한 번을 하려면:
→ 총 2번의 메모리 접근이 필요하다. 이 오버헤드를 줄이기 위해 자주 쓰는 매핑을 TLB에 저장한다.
<p, d> (page number, offset) 생성<f, d> 생성


프로그램 전체를 메모리에 올릴 필요가 없다. 실제로는 프로그램의 일부만 실행되고, 나머지는 거의 쓰이지 않는다.
프로그램 실행 중 실제로 필요한 페이지만 메모리에 올린다. 한 번도 접근하지 않는 페이지는 영원히 물리 메모리에 올라오지 않는다.

v(valid)로 설정

프로세스가 메모리에 올라와 있지 않은 페이지에 접근을 시도할 때, 즉 valid-invalid bit가 i(invalid)인 페이지에 접근할 때 발생하는 예외(exception/trap)이다.



| 구분 | Page Fault | Segmentation Fault |
|---|---|---|
| 원인 | 유효한 주소이나 메모리에 없음 | 잘못된/허용되지 않은 주소 접근 |
| 복구 | 가능 (페이지 로딩 후 재시작) | 불가능 (프로세스 종료) |

Effective Access Time = (1 - p) × ma + p × page_fault_time
ma: Memory access time (보통 10~200 나노초)p: Page fault rate (0 ≤ p ≤ 1)→ 평균 page fault service time ≈ 8ms

EAT = (1 - 1/1000) × 200 + (1/1000) × 8,000,000
= 199.8 + 8000
= 8,199.8ns ≈ 8.2μs
→ Page fault가 1000번에 1번만 발생해도 메모리 접근 시간이 약 40배 느려진다!

Page fault 발생 시 free frame이 없으면 어떻게 할 것인가?

| 방법 | 설명 | 단점 |
|---|---|---|
| Solution 1: Process Termination | 페이지 폴트를 일으킨 프로세스 종료 | 너무 극단적 |
| Solution 2: Process Swapping (Swap-Out) | 프로세스 전체를 디스크로 내보냄 | 오버헤드 큼 |
| Solution 3: Page Replacement | 사용 안 하는 frame 하나를 찾아 교체 | 가장 일반적 |

i로 변경| 구분 | 단위 | 목적 |
|---|---|---|
| Page-Out | 페이지 1개 | Victim 페이지를 swap space로 |
| Swap-Out | 프로세스 전체 | 프로세스의 모든 페이지를 디스크로 |

Page replacement 시 disk I/O를 줄이기 위한 최적화이다.

메모리 참조의 순서를 나열한 것. 교체 알고리즘을 평가할 때 사용한다.
예시: 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1


방법: 메모리에 가장 오래 머물러 있던 페이지를 교체한다. (들어온 순서대로 쫓아냄)
구현: FIFO queue. Queue의 head에 있는 페이지를 교체.
예시 (3 frames, reference string: 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1):
→ 15번 page fault
장점: 구현이 매우 간단
단점: 자주 사용되는 페이지도 오래됐다는 이유로 쫓아낼 수 있음

방법: 앞으로 가장 오래 사용되지 않을 페이지를 교체한다.
문제: 미래의 reference string을 알아야 하므로 실제 구현 불가능
용도: 다른 알고리즘의 성능을 비교하기 위한 이론적 하한선(baseline)

예시 (3 frames, 같은 reference string): → 9번 page fault (최소)

방법: 가장 오랫동안 사용되지 않은 페이지를 교체한다.
핵심 아이디어: "미래를 볼 수 없으니, 과거를 보고 추정하자" → OPT의 근사(approximation)
예시 (3 frames, 같은 reference string): → 12번 page fault
구현 방법 1: Counter

구현 방법 2: Stack

결론: 순수 LRU는 하드웨어 지원 없이는 오버헤드가 너무 커서 실용적이지 않다.

실제 컴퓨터 시스템은 순수 LRU를 지원할 만한 충분한 하드웨어를 제공하지 않는다. 따라서 근사(approximation) 기법이 필요하다.

기본 구조: Circular queue + clock pointer
동작:
1. 포인터가 가리키는 페이지의 reference bit 확인
2. bit = 0 → 이 페이지를 교체 (victim)
3. bit = 1 → bit를 0으로 클리어하고 다음 페이지로 이동 (second chance 부여)
4. 한 바퀴 돌아와도 모두 1이면 → 결국 처음 페이지가 교체됨 (모든 bit가 0으로 클리어된 상태)

핵심: FIFO의 단순함 + reference bit로 최근 사용 여부 반영

동기: 수정된(dirty) 페이지를 교체하면 디스크에 write가 필요해서 시간이 더 걸린다. I/O를 줄일 필요가 있다.
방법: Reference bit + Modify bit(dirty bit)를 ordered pair로 사용
| (reference, modify) | 의미 | 교체 우선순위 |
|---|---|---|
| (0, 0) | 최근 사용 안 됨 + 수정 안 됨 | 최우선 교체 (best) |
| (0, 1) | 최근 사용 안 됨 + 수정됨 | 차선 (교체 시 disk write 필요) |
| (1, 0) | 최근 사용됨 + clean | 곧 다시 쓰일 가능성 |
| (1, 1) | 최근 사용됨 + 수정됨 | 최후 순위 (worst) |
효과: 단순 Second-Chance보다 disk I/O를 줄일 수 있음

각 페이지의 참조 횟수를 counter로 관리한다.
| 알고리즘 | 방법 | 근거 |
|---|---|---|
| LFU (Least Frequently Used) | 참조 횟수가 가장 적은 페이지 교체 | 적게 쓰인 페이지 = 앞으로도 안 쓰일 것 |
| MFU (Most Frequently Used) | 참조 횟수가 가장 많은 페이지 교체 | 적게 쓰인 페이지 = 방금 들어와서 아직 안 쓰인 것 |
단점: 큰 메모리 필요 + 적절한 count 값을 가진 페이지를 찾는 탐색 오버헤드
만약 counter 4byte를 page table에 추가하면 page table의 frame(page)증가
실제 OS 구현은 방법이 없다
| 알고리즘 | Page Fault (3 frames) | 실용성 | 핵심 특징 |
|---|---|---|---|
| FIFO | 15 | ⭐⭐⭐ | 가장 간단 |
| OPT | 9 | ❌ (구현 불가) | 이론적 최적 |
| LRU | 12 | ⭐⭐ (오버헤드 큼) | 과거 기반 OPT 근사 |
| Second-Chance | - | ⭐⭐⭐ | FIFO + reference bit |
| Enhanced Second-Chance | - | ⭐⭐⭐ | + dirty bit로 I/O 최적화 |
OPT (이론적 최적, 구현 불가)
↓ 근사
LRU (정확하지만 오버헤드 큼)
↓ 근사
Reference Bit (싸지만 순서 모름)
↓ 활용
Second-Chance / Clock (FIFO + reference bit)
↓ 개선
Enhanced Second-Chance (+ dirty bit로 I/O 최적화)

프로세스가 active하게 사용하는 페이지를 담을 frame이 부족하여, 빈번하고 빠르게 page fault가 반복 발생하는 현상이다.

Solution 1: Local Replacement Algorithm
Solution 2: Locality Model 기반 Working-Set

Locality: 함께 활발하게 사용되는 페이지들의 집합

| 유형 | 설명 | 예시 |
|---|---|---|
| Temporal Locality (시간적 지역성) | 최근 접근한 데이터가 곧 다시 접근될 가능성 | 루프에서 같은 변수 반복 참조 |
| Spatial Locality (공간적 지역성) | 접근한 위치 근처의 데이터가 곧 접근될 가능성 | 배열 순차 접근, 함수 호출 시 인접 코드 |

예: Func0(page 11)이 malloc(page 12)을 호출하고 Func1(page 10)을 호출하면, page 10, 11, 12가 함께 사용되는 locality를 형성한다.
→ 이 locality의 페이지들을 모두 메모리에 유지하면 page fault를 줄일 수 있다.


page reference table:
...2 6 1 5 7 7 7 5 1 6 2 3 4 1 2 3 4 4 3 4 3 4 4 1 3 2 3 4 4 3 4 4 4...
↑ t1 ↑ t2


fork() 시 부모 프로세스의 메모리를 자식에게 전부 복사하면 오버헤드가 크다.
| 용어 | 영문 | 설명 |
|---|---|---|
| 요구 페이징 | Demand Paging | 필요한 페이지만 메모리에 올리는 기법 |
| 페이지 폴트 | Page Fault | 메모리에 없는 페이지에 접근 시 발생하는 예외 |
| 페이지 교체 | Page Replacement | free frame이 없을 때 victim을 골라 교체 |
| Page-In | Page-In | 디스크 → 물리 메모리 (페이지 1개) |
| Page-Out | Page-Out | 물리 메모리 → 디스크 (페이지 1개) |
| Swap-Out | Swap-Out | 프로세스 전체를 디스크로 내보냄 |
| 참조 비트 | Reference Bit | 페이지 참조 시 하드웨어가 설정하는 비트 |
| 수정 비트 | Modify/Dirty Bit | 페이지 수정 시 하드웨어가 설정하는 비트 |
| 쓰래싱 | Thrashing | 빈번한 page fault로 CPU가 거의 일을 못 하는 상태 |
| 지역성 | Locality | 함께 사용되는 페이지들의 집합 |
| 작업 집합 | Working Set | 최근 Δ번 참조에서 접근된 페이지 집합 |
| 쓰기 시 복사 | Copy-On-Write | fork() 시 실제 write가 발생할 때만 페이지 복사 |
| 유효 접근 시간 | Effective Access Time | page fault율을 반영한 실제 메모리 접근 시간 |