PML4: 왜 큰 페이지 테이블 하나로는 안 될까?

“그냥 큰 페이지 테이블과 그 안에 포인터를 쓰면 되는 거 아닌가?”라는 의문에서 시작해 64비트 시스템의 다단계 페이지 테이블(PML4)을 살펴본다.

1. PML4란?

PML4는 64비트 시스템에서 사용하는 다단계 페이지 테이블의 최상위 단계다. 여기서 “그냥 큰 페이지 테이블 하나에 포인터를 쓰면 되는 것 아닌가?”라는 의문이 들 수 있는데, 그게 왜 비효율적인지부터 살펴보자.

2. 왜 PML4(다단계)가 필요한가?

64비트 시스템은 이론상 2⁶⁴ = 16엑사바이트(EB)의 주소 공간을 표현할 수 있다. 하지만 현실적으로 x86-64 아키텍처는 48비트만 사용한다 (2⁴⁸ = 256TB).

이를 4KB 페이지로 나누면 필요한 페이지 수는 다음과 같다.

항목 계산 결과
주소 공간 2⁴⁸ 256 TB
페이지 크기 2¹² 4 KB
총 페이지 수 2⁴⁸ / 2¹² = 2³⁶ 약 687억 개

단일 테이블로 쓴다면?

엔트리 하나가 8바이트(64bit)라면, 2³⁶ × 8B = 512GB짜리 단일 테이블이 필요하다. 게다가 이걸 프로세스마다 따로 관리해야 한다. 메모리 낭비가 엄청나다.

다단계 페이징의 핵심 아이디어

전체 주소 공간 중 실제로 쓰는 부분만 테이블로 만들자. 테이블을 트리 구조로 나눠 필요한 만큼만 동적으로 할당하는 방식이다.

단계 엔트리 수 다음 단계
PML4 512 → PDP
PDP 512 → PD
PD 512 → PT
PT 512 → 실제 물리 페이지

이 구조의 장점은 다음과 같다.

장점 설명
메모리 절약 안 쓰는 주소 공간은 테이블 자체를 만들지 않음
유연성 프로세스마다 필요한 주소 영역만 테이블 구성
격리·보호 계층 구조에서 각 테이블을 독립적으로 관리

3. PML4 개념과 주소 변환

3-1. 가상 주소 구조 (48비트)

| PML4 (9bit) | PDP (9bit) | PD (9bit) | PT (9bit) | Offset (12bit) |
  • 각 테이블 인덱스는 9비트 = 512개 엔트리 (2⁹)
  • Offset 12비트는 4KB 페이지 내부의 주소
  • 총 페이지 수: 2⁽⁴⁸⁻¹²⁾ = 2³⁶개

3-2. 4단계 주소 변환 흐름

가상 주소를 따라 4단계 테이블을 타고 내려가 물리 주소를 얻는다.

PML4 ──(9bit)──▶ PDP ──(9bit)──▶ PD ──(9bit)──▶ PT ──(9bit)──▶ 물리 페이지(4KB)
                                                              + Offset(12bit)

각 단계에서 9비트로 512개 엔트리 중 하나를 골라 다음 테이블의 주소를 얻고, 마지막 PT에서 물리 페이지를 찾은 뒤 Offset을 더해 최종 물리 주소를 완성한다.

3-3. 필요한 만큼만 만든다

핵심은 필요한 테이블만 동적으로 생성한다는 점이다. 예를 들어 4KB 페이지 단 하나만 쓴다면, PML4 + PDP + PD + PT 테이블 4개와 물리 페이지 1개만 있으면 된다. 512GB짜리 단일 테이블과 비교하면 압도적으로 효율적이다.

4. PintOS와 다단계 페이징

PintOS는 x86-64 기반의 4단계 페이징 구조를 사용한다. 관련 함수는 다음과 같다.

함수 역할
pml4_create() 새 PML4 테이블 생성
pml4_set_page(pml4, va, pa, writable) 가상주소 va를 물리주소 pa에 매핑
pml4_get_page(pml4, va) va에 매핑된 pa 조회
pml4_activate(pml4) 현재 CPU가 사용할 페이지 테이블로 설정

pml4va가 함께 쓰이는데, pml4는 지도, va는 좌표라고 생각하면 이해하기 쉽다.

프로세스마다 다른 pml4

  • struct thread 안에 pml4 멤버가 있다
  • 프로세스 전환 시, 커널은 cr3 레지스터에 해당 프로세스의 pml4 물리 주소를 설정해 주소 공간을 전환한다

© 2022 JeongHwan Yun.