[OS] 메모리 관리 기법 - 페이징 (2)

semin·2024년 6월 11일
post-thumbnail

개요

1편에서 메모리 연속 할당과 단편화를 페이징을 통해 해결하는 개념을 살펴보았다. 2편에서는 페이지 테이블의 연속할당은 어떻게 해결하는지, 메모리 접근으로 인한 성능 문제는 어떻게 해결하는지 알아보자.

단순 페이지 테이블의 문제

64bit 프로세서에서 가상 메모리는 page number를 위해 36bit를 사용한다고 했다. 이 때 페이지 테이블의 크기를 계산하면 다음과 같다.

페이지 테이블 엔트리(페이지 테이블의 row) 의 개수: 2^36개
2^36 * 8byte (1word = 64bit = 8byte) = 512GB

연속할당과 단편화를 해결하기 위해 페이징과 페이지 테이블이라는 방식을 고안했는데, 이를 구현하기 위해 512GB라는 연속된 메모리 주소공간이 필요하게 되었다. 이를 어떻게 해결할 수 있을까?

계층적 페이지 테이블 (Multi-level/Hierarchical page table)

현대적 OS에서는 페이지 테이블의 연속 할당 문제를 해결하기 위해 주로 계층적 페이지 테이블 구조를 사용한다.
계층적 페이지 테이블은 페이지 번호를 표현하기 위해 사용하는 비트를 나눠서 페이지를 계층적으로 표현하는 것이다. 다음 그림을 통해 좀 더 쉽게 알아보자.

32bit 프로세서에서 계층적 페이지 테이블을 구현하기 위해 주소를 위와 같이 나타낼 수 있다. 위와 같이 비트를 나누면 아래와 같은 계층적 페이지 테이블 구조를 구현할 수 있게 된다.


계층별로 2^(할당된 비트 수) 만큼 페이지를 가지고 있는 계층적 페이지 테이블 구조가 구현된다.

31-22bit의 정보를 통해 1계층 페이지 테이블 엔트리를 찾아낸 뒤 2계층 페이지 테이블의 물리 주소를 획득한다. 다음으로는 21-12bit의 정보를 통해 2계층 페이지 테이블 엔트리를 찾고, 물리 메모리의 페이지 번호를 획득한다. 마지막으로 페이지 번호와 11-0bit의 오프셋 정보를 조합하여 정확한 물리주소를 획득하여 메모리에 특정 주소에 접근할 수 있게 된다.

이렇게 계층을 나누면 두가지 장점을 가지게 된다.

  1. 페이지 테이블을 메모리에 연속된 공간에 할당할 필요가 없다.
  2. 현재 프로그램 실행에 필요한 부분만 메모리에 적재하고 페이지 테이블과 매핑하여 메모리를 효율적으로 사용할 수 있다.

계층적으로 페이지 테이블을 나눈다고 하더라도 모든 페이지를 처음부터 매핑하려 한다면 1계층에서는 2^10개의 페이지 엔트리를 가지게 되고 2계층에서는 1계층의 각각에 엔트리에 매핑되는 2^10개의 엔트리를 가지는 2^10개의 페이지 테이블을 가지게 되므로 기존보다 많은 크기의 메모리를 할당해야 하는 것 처럼 보이지만 필요한 만큼만 메모리에 적재하고 페이지 테이블과 매핑할 수 있다.

두번째 장점인 필요한 부분만 메모리에 적재하고, 페이지 테이블에 매핑함으로써 프로그램 전체를 메모리에 적재하지 않고도 프로그램을 실행할 수 있는 가상메모리 구현이 가능해진다.

가상메모리란?
가상 메모리는 프로세스 전체를 메모리에 할당하지 않고도 실행할 수 있도록 하는 기술이다.

만약 100GB가 넘는 게임을 컴퓨터로 실행한다면, 디스크에서는 프로그램을 실행할 수 없으므로 해당 게임을 메모리에 적재해야 할 것이다. 그런데, 우리가 사용하는 메인메모리의 공간은 보통 16GB~32GB 일 것이다. 그렇다면 이 게임은 그 이상의 메인 메모리를 장착해야 실행할 수 있는가? 그렇지 않다. 지금까지 설명한 가상주소, 페이징과 페이지 테이블 기법을 통해서 프로세스 수행에 필요한 부분만 메모리에 적재하여 실행하는 것이다. 게임을 하며 맵을 이동할 때 로딩을 기다리는 것도 사용하지 않아 메모리에 로드되지 않은 프로그램의 일부를 로드하는 작업 때문이라고 할 수 있다.

x86-64 아키텍처에서의 계층적 페이지 테이블

위에서 계층적 페이지 테이블을 쉽게 이해할 수 있도록 32bit 아키텍처로 예시를 들어 설명했다. 현대적으로 가장 많이 사용하는 x86-64 아키텍처에서는 실제로 어떻게 페이지 테이블을 구현하는지 자세하게 알아보자.

x86-64 아키텍처에서는 다음과 같은 4계층의 페이지 테이블 기법을 채택하였다.

  1. PML4 (Page Map Level 4)
  2. PDPT (Page Directory Pointer Table)
  3. PDT (Page Directory Table)
  4. PT (Page Table)

각각의 명칭이 있지만 순서대로 다음 계층의 페이지 테이블의 물리 주소를 가리키고 있다고 생각하면 쉬울 것이다.


1편에서 추가 설명했듯이 x86-64 아키텍처는 가상주소를 48bit만 사용하며 그 중 36bit를 페이지 번호를 나타내기 위해 사용한다고 하였다.

36bit를 다음과 같이 계층별로 9bit씩 사용하여 계층을 나타낸다.

비트 위치사용 용도
47-39PML4 엔트리 인덱스
38-30PDPT 엔트리 인덱스
29-21PDT 엔트리 인덱스
20-12PT 엔트리 인덱스
11-0페이지 오프셋 (Page Offset)

페이지 테이블의 하나의 행을 페이지 테이블 엔트리(PTE) 라고 하며, 각각의 엔트리는 아래와 같이 1 word(64bit) 크기를 가진다.

위와 같이 0번째 비트는 페이지가 메모리에 로드 되었고 유효한지 확인하는 비트로 활용되고, 12~51번째 비트는 물리 주소를 가리킨다. 그 외에도 페이지 접근 권한, 접근 여부, 수정 여부 등 다양한 정보를 가지고 있다. x86-64 아키텍처의 물리 주소는 40bit(페이지 번호 28bit + 페이지 오프셋 12bit) 를 사용한다고 했으니, 페이지 테이블 엔트리가 가리키는 물리주소와 정확하게 매핑할 수 있음을 이해할 수 있다.

참고자료

https://charles098.tistory.com/108
https://velog.io/@junttang/OS-2.6-MV-6-Multi-Level-Page-Tables

profile
블로그 이전 -> https://choicco.tistory.com/

0개의 댓글