작은 크기 페이지들인 Large Page(64KB)와 Small Page(4KB)를 사용하고자 할 때는 2단계 페이징을 합니다.
물론 크기가 작은 페이지도 하나의 페이지 테이블을 활용하는 1단계 페이징으로 할 수 있습니다만, 이것은 매우 비효율적입니다. 예를 들어, 4KB 페이지를 하나의 페이지 테이블로 페이징한다고 가정해 봅시다.
32비트 머신에서 가장 주소 공간은 4GB이므로, 총 1048576개의 엔트리가 필요합니다.
하나의 엔트리 크기는 4B이므로, 페이지 테이블의 크기는 총 4MB가 됩니다. 페이지 테이블은 프로세스마다 존재하므로 프로세스를 생성할때마다 페이지 테이블 용도로 4MB 메모리 공간을 할당하는 것은 낭비가 너무 심합니다.
이것을 2단계 페이징으로 변경하면, 16KB 크기의 1단계 페이지 테이블을 할당하고, 2단계 페이지 테이블은 가상 주소 영역에서 필요한 공간만 할당해서 사용할 수 있습니다.
이것이 다단계 페이징을 하는 이유입니다.
앞으로 2단계 페이지 테이블도 L1 페이지 테이블과 마찬가지로 L2 페이지 테이블(Level 2 Page Table)이라고 하겠습니다.
<그림 4>는 2단계 페이징 과정을 보여줍니다.
MMU는 우선 TTBA(Translation Table Base Address)에서 L1 페이지 테이블의 시작 주소를 얻어옵니다.
L1 페이지 테이블의 시작 주소에서 가상 주소 [31..20] 비트를 오프셋으로 사용하여 접근하려는 L1 페이지 테이블 엔트리의 주소를 구합니다(Level 1 Descriptor Address).
L1 페이지 테이블 엔트리에서는 2단계 페이지 테이블 시작 주소가 저장되어 있습니다.
L2 페이지 테이블 시작 주소(Level 2 Table Base Address)에서 가상 주소 [19..12] 비트를 오프셋으로 사용하여 L2 페이지 테이블 엔트리(L2 Page Table Entry)의 주소를 구합니다(Level 2 Descriptor Address).
메모리에서 L2 페이지 테이블 엔트리를 읽어오면, L2 페이지 테이블 엔트리에 저장된 가상 주소에 해당하는 페이지 프레임의 시작 주소(Small Page Base Address)를 알 수 있습니다.
마지막으로 페이지 프레임의 시작 주소에서 가상 주소 [11..0] 비트를 오프셋으로 사용하여 최종 접근하는 물리 주소(Physical Address)를 구하게 됩니다.
사실 2단계 페이징은 단계만 하나 늘었다뿐이지 1단계 페이징과 별반 다른점이 없습니다.
<L1 페이지 테이블 시작 주소>, <L2 페이지 테이블 시작 주소>, <페이지 프레임 시작 주소>는 각각 <TTBA>, <L1 페이지 테이블 엔트리>, <L2 페이지 테이블 엔트리>에 저장되어 있고, 가상 주소를 나눠서 오프셋(인덱스)으로 사용한다는 점만 유념합시다.
2단계 페이징 과정도 좀 더 명확하게 이해하기 위해 예를 들어 볼까요? 아래와 같이 가정하고 2단계 페이징이 어떻게 되는지 보겠습니다.
가상 주소 = 0xC0010010
물리 주소 = 0x00010010
L1 페이지 테이블 시작 주소 = 0x4000
L2 페이지 테이블 시작 주소 = 0x9000
먼저 TTBA에 저장된 L1 페이지 테이블 시작 주소에서 L1 페이지 테이블 시작 주소를 얻어옵니다. L1 페이지 테이블 시작 주소에서 가상 주소의 [31..20] 비트를 오프셋으로 사용하여 L1 페이지 테이블 엔트리를 구합니다.