페이징 메커니즘 — 가상 주소가 물리 주소로 변환되는 과정
페이지(Page)란?
메모리는 페이지(Page)라는 단위로 관리됩니다. x86/x64에서 기본 페이지 크기는 4KB(4096 바이트)예요. 가상 메모리도, 물리 메모리도 모두 4KB 단위로 나뉘어 관리됩니다.
왜 4KB냐고요? 역사적 이유와 TLB 효율성의 균형점이 4KB라는 게 밝혀졌기 때문이에요. 너무 작으면 페이지 테이블 엔트리가 너무 많아지고, 너무 크면 내부 단편화가 심해지거든요.
페이지 테이블 — 변환 표
가상 주소 → 물리 주소 변환은 페이지 테이블(Page Table)을 통해 이루어져요. 페이지 테이블은 간단히 말하면 "가상 페이지 번호 → 물리 페이지 번호" 매핑 표입니다.
x64에서는 4단계 페이지 테이블(4-Level Paging)을 사용해요:
- PML4 (Page Map Level 4) — CR3 레지스터가 가리키는 최상위 테이블
- PDPT (Page Directory Pointer Table)
- PD (Page Directory)
- PT (Page Table) — 최하위. 여기의 엔트리(PTE)가 최종 물리 주소를 담음
48비트 가상 주소는 다음과 같이 분해됩니다:
가상 주소 (48비트): [47:39] [38:30] [29:21] [20:12] [11:0] PML4 PDPT PD PT Page Offset 9 bits 9 bits 9bits 9bits 12 bitsCPU(MMU)는 이 인덱스들을 순서대로 따라가면서 최종 물리 주소를 찾아냅니다. 이 과정을 페이지 테이블 워크(Page Table Walk)라고 해요.
PTE — 페이지 테이블 엔트리
페이지 테이블의 각 엔트리를 PTE(Page Table Entry)라고 해요. 8바이트(64비트) 크기이며, 단순히 물리 주소만 담는 게 아니라 여러 플래그를 포함해요:
| 비트 | 이름 | 의미 |
|---|---|---|
| 0 | Present (P) | 1이면 물리 메모리에 있음, 0이면 스왑됨 또는 미할당 |
| 1 | Read/Write (RW) | 0이면 읽기 전용 |
| 2 | User/Supervisor (US) | 0이면 커널 모드만 접근 가능 |
| 5 | Accessed (A) | 이 페이지에 접근한 적 있으면 CPU가 자동으로 1로 설정 |
| 6 | Dirty (D) | 이 페이지에 쓴 적 있으면 1 — 스왑 아웃 시 디스크에 써야 함을 표시 |
| 63 | No Execute (NX) | 1이면 이 페이지의 코드 실행 불가 (DEP/NX 기능) |
| 12~51 | Physical Frame Number | 물리 페이지의 주소 (12 왼쪽 시프트하면 물리 주소) |
페이지 폴트(Page Fault) — 없는 페이지를 읽으면?
Present 비트가 0인 페이지에 접근하면 CPU가 페이지 폴트 예외(#PF, Interrupt 14)를 발생시켜요. OS의 페이지 폴트 핸들러가 이 예외를 받아서 다음 중 하나를 처리합니다:
- 정상적 페이지 폴트 — 스왑 파일에서 페이지를 읽어와 물리 메모리에 올려놓고 재시도 → 앱은 모름
- Demand Paging — 처음 할당 시 물리 메모리를 바로 안 줌. 실제로 접근하면 그때 할당
- Copy-on-Write — fork() 등에서 공유 페이지에 쓰기 시도 시 새 물리 페이지 할당
- 접근 위반 — 유저 모드에서 커널 페이지에 접근하거나, 없는 주소에 접근 → Access Violation 예외로 앱에 전달
TLB — 변환 캐시
4단계 페이지 테이블 워크는 매번 수행하면 메모리를 4번 읽어야 하는 셈이에요. 이 오버헤드를 줄이기 위해 CPU에는 TLB(Translation Lookaside Buffer)라는 캐시가 있어요.
TLB는 "이 가상 주소는 이 물리 주소"라는 변환 결과를 캐싱해 두었다가, 같은 주소가 다시 오면 페이지 테이블 워크 없이 바로 변환 결과를 돌려줍니다.
그런데 다른 프로세스로 컨텍스트 스위치가 일어나면, 이전 프로세스의 TLB 엔트리가 다 무효화되어야 해요. 이게 컨텍스트 스위치 비용의 상당 부분을 차지합니다.
WinDbg로 PTE 직접 보기
WinDbg 커널 디버거에서 아래 명령으로 특정 가상 주소의 PTE를 조회할 수 있어요:
; 가상 주소 0xFFFF...의 PTE 조회 !pte 0xffff800000000000 ; 출력 예시: ; VA ffff800000000000 ; PXE at FFFFF6FB7DBED800 PPE at FFFFF6FB7DB00000 PDE at FFFFF6FB60000000 PTE at FFFFF68000000000 ; contains 00000000`001AD063 contains 00000000`00246063 ... ; pfn 1ad ---DA--KWEV pfn 246 ---DA--KWEV ...여기서 pfn은 Physical Frame Number, K는 커널만 접근 가능, W는 쓰기 가능을 의미해요.
- 메모리는 4KB 페이지 단위로 관리됩니다.
- x64는 4단계 페이지 테이블(PML4 → PDPT → PD → PT)로 가상→물리 주소 변환을 합니다.
- PTE에는 물리 주소 외에 Present, RW, US, NX 등 다양한 플래그가 있습니다.
- 없는 페이지에 접근하면 페이지 폴트가 발생하고 OS가 처리합니다.
- TLB가 변환 결과를 캐싱해서 성능을 높여요. 컨텍스트 스위치 시 TLB가 플러시됩니다.
#페이징 #PageTable #PTE #TLB #페이지폴트
'Programming > 7. Device Driver' 카테고리의 다른 글
| Windows 아키텍처 기초 - 7화 Windows I/O 시스템 개관 (0) | 2026.05.25 |
|---|---|
| Windows 아키텍처 기초 - 6화 프로세스와 스레드 (0) | 2026.05.23 |
| Windows 아키텍처 기초 - 4화 가상 메모리와 주소 공간 (0) | 2026.05.21 |
| Windows 아키텍처 기초 - 3화 커널 모드 vs 유저 모드 (0) | 2026.05.20 |
| Windows 아키텍처 기초 - 2화 Windows OS 구조 개관 (0) | 2026.05.19 |