MMU
CPU와 물리 메모리 사이에 위치하여 가상 주소를 물리 주소로 변환하고 메모리 접근 권한을 검사하는 하드웨어 장치입니다.
핵심 역할
| 역할 | 설명 |
|---|---|
| 주소 변환 | 가상 주소(VA) → 물리 주소(PA) 변환 |
| 메모리 보호 | 프로세스별 접근 권한(R/W/X) 검사 |
| 메모리 격리 | 프로세스 간 주소 공간 분리 |
| 캐시 제어 | TLB를 통한 주소 변환 결과 캐싱 |
MMU의 위치
┌──────────┐ 가상 주소 ┌──────────┐ 물리 주소 ┌──────────┐
│ │ ──────────────→ │ │ ──────────────→ │ │
│ CPU │ │ MMU │ │ 물리 메모리 │
│ │ ←────────────── │ │ ←────────────── │ (RAM) │
└──────────┘ 데이터 └──────────┘ 데이터 └──────────┘
│
▼
┌──────────┐
│ TLB │ 주소 변환 캐시
└──────────┘
주소 변환 과정 (페이징 기반)
가상 주소 (예: 0x00403004)
┌──────────────┬──────────────┐
│ 페이지 번호 │ 오프셋 │
│ (VPN: 0x403) │ (0x004) │
└──────┬───────┴──────┬───────┘
│ │
▼ │
페이지 테이블 조회 │
VPN → PFN 변환 │
│ │
▼ ▼
┌──────────────┬──────────────┐
│ 프레임 번호 │ 오프셋 │
│ (PFN: 0x7A1) │ (0x004) │
└──────────────┴──────────────┘
물리 주소 (0x7A1004)
TLB (Translation Lookaside Buffer)
페이지 테이블 조회는 메모리 접근이 필요하므로 느립니다. TLB는 최근 변환 결과를 캐싱하여 속도를 높입니다.
CPU → 가상 주소 발행
│
▼
TLB 조회 (하드웨어 캐시)
│
├── TLB Hit → 즉시 물리 주소 반환 (~1 사이클)
│
└── TLB Miss → 페이지 테이블 조회
│
├── Valid Bit = 1 → 물리 주소 반환 + TLB 갱신
│
└── Valid Bit = 0 → Page Fault → 커널이 디스크에서 로드
| 항목 | TLB Hit | TLB Miss (테이블 Hit) | Page Fault |
|---|---|---|---|
| 소요 시간 | ~1 ns | ~10-100 ns | ~수 ms |
| 메모리 접근 | 0회 (캐시) | 1~4회 (테이블 계층) | 디스크 I/O |
| 빈도 | 약 95~99% | 1~5% | 매우 드묾 |
다단계 페이지 테이블
단일 페이지 테이블은 크기가 너무 커서, 현대 OS는 다단계 구조를 사용합니다.
[x86-64: 4단계 페이지 테이블]
가상 주소 (48비트 사용)
┌────────┬────────┬────────┬────────┬──────────┐
│ PML4 │ PDPT │ PD │ PT │ Offset │
│ (9bit) │ (9bit) │ (9bit) │ (9bit) │ (12bit) │
└───┬────┴───┬────┴───┬────┴───┬────┴────┬─────┘
│ │ │ │ │
▼ ▼ ▼ ▼ │
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ PML4 │→│ PDPT │→│ PD │→│ PT │──→ PFN + Offset
│ Table│ │ Table│ │ Table│ │ Table│ = 물리 주소
└──────┘ └──────┘ └──────┘ └──────┘
↑
│
CR3 레지스터 (페이지 테이블 시작 주소)
| 단계 | 이름 | 역할 |
|---|---|---|
| 1단계 | PML4 (Page Map Level 4) | 최상위 디렉토리 |
| 2단계 | PDPT (Page Directory Pointer Table) | 2번째 디렉토리 |
| 3단계 | PD (Page Directory) | 3번째 디렉토리 |
| 4단계 | PT (Page Table) | 최종 프레임 번호 매핑 |
MMU의 메모리 보호
| 보호 유형 | 설명 | 위반 시 |
|---|---|---|
| 읽기/쓰기/실행 권한 | 페이지별 R/W/X 권한 설정 | General Protection Fault |
| 사용자/커널 구분 | 커널 페이지에 사용자 접근 차단 | General Protection Fault |
| Valid Bit 검사 | 매핑되지 않은 주소 접근 차단 | Page Fault |
| NX Bit (No-eXecute) | 데이터 영역 코드 실행 방지 | 보안 예외 |
// MMU가 보호하는 상황 예시
// 1. NULL 접근 → 매핑되지 않은 주소 → Page Fault → SIGSEGV
Object obj = null;
obj.toString(); // JVM이 NullPointerException으로 변환
// 2. 코드 영역에 쓰기 시도 → W 권한 없음 → Protection Fault
// (Java에서는 JVM이 방지하지만, C에서는 Segfault 발생)
// 3. 다른 프로세스 메모리 접근 시도 → 매핑 없음 → Page Fault
// (각 프로세스는 독립된 페이지 테이블 → 서로 접근 불가)
컨텍스트 스위칭과 MMU
프로세스가 전환되면 CR3 레지스터가 변경되어 새 프로세스의 페이지 테이블을 가리킵니다.
프로세스 A 실행 중 컨텍스트 스위칭 프로세스 B 실행
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ CR3 → A의 │ → │ CR3 변경 │ → │ CR3 → B의 │
│ 페이지 테이블 │ │ + TLB Flush │ │ 페이지 테이블 │
└──────────────┘ └──────────────┘ └──────────────┘
※ CR3 변경 시 TLB가 무효화되므로 전환 직후 TLB Miss 증가 → 성능 저하
이를 줄이기 위해 ASID(Address Space ID) 태깅 기법 사용
Java에서 MMU가 관여하는 상황
// 1. 객체 생성 → JVM이 힙 메모리 할당 → MMU가 가상→물리 변환
Object obj = new Object();
// 2. 큰 배열 → 가상 메모리 확보, 접근 시 MMU가 변환 + 페이지 폴트 가능
byte[] data = new byte[50 * 1024 * 1024]; // 50MB
data[0] = 1; // MMU: 가상주소 → 물리주소 변환 (첫 접근 시 Page Fault)
// 3. 메모리 매핑 파일 → MMU가 파일 오프셋을 가상 주소로 매핑
FileChannel fc = FileChannel.open(Path.of("data.bin"));
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
byte b = mbb.get(0); // MMU가 가상주소 변환, 필요 시 Page Fault
// 4. JVM GC → 객체 이동 시 페이지 테이블 갱신 필요
System.gc(); // 살아있는 객체를 새 영역으로 복사 → MMU 매핑 갱신