모든 이야기

페이징: 메모리를 같은 크기의 조각으로 나누면 무엇이 달라질까

여러 프로그램에 메모리를 배정할 때 전체 공간을 각 프로그램 크기에 맞는 덩어리로 나누면 빈틈이 생기기 쉽다. 페이징은 가상 주소 공간을 고정 크기의 페이지로, 물리 메모리를 같은 크기의 프레임으로 나누어 연결하는 방법이다. 프로그램의 논리적으로 연속된 영역이 RAM에서는 떨어진 프레임에 배치돼도 동작할 수 있다.

연속된 가상 배열의 세 페이지가 떨어진 물리 프레임에 연결되는 그림과 마지막 페이지의 미사용 공간

페이징은 물리 배치의 불연속성을 숨기지만 마지막 페이지에 내부 낭비가 생길 수 있다.

연속성은 프로그램이 보는 성질

12KiB의 가상 배열을 4KiB 페이지로 나누면 세 페이지가 필요하다. 이 페이지들을 물리 프레임 2, 10, 6에 놓아도 프로그램은 하나의 연속된 배열처럼 읽는다. 각 페이지의 변환표만 올바르면 페이지 경계에서 다른 프레임으로 넘어간다. 연속된 가상 주소가 항상 연속된 물리 주소를 뜻하지 않는다는 점이 핵심이다.

주소는 페이지 번호와 페이지 내부 오프셋으로 나뉜다. 번호는 변환표를 통해 프레임 번호로 바뀌고 오프셋은 유지된다. OSTEP의 페이징 장은 이 규칙과 고정 크기 분할의 의미를 설명한다. 가상 주소를 한 덩어리의 숫자로만 볼 때보다 어느 부분이 변환되는지 파악하기 쉽다.

빈틈을 없애면 다른 낭비가 생긴다

일반적인 페이지 단위 배정은 필요한 프레임을 어디서든 확보할 수 있어 가변 크기 연속 배정에서 생기는 외부 단편화 문제를 줄인다. 그러나 마지막 페이지를 덜 쓰면 남은 부분이 내부 낭비가 된다. 예를 들어 10KiB를 4KiB 단위로 배정하면 12KiB를 확보하고 2KiB는 사용하지 않는다. 큰 페이지일수록 이런 낭비가 커질 수 있다.

페이지 크기를 작게 하면 작은 할당에 대한 낭비는 줄지만, 같은 주소 공간에 더 많은 페이지 테이블 항목이 필요하다. 큰 페이지는 관리 항목을 줄이고 변환 캐시가 덮는 범위를 넓히지만, 큰 물리 구간을 확보하고 옮기는 부담이 생긴다. 따라서 페이지 크기는 용량 효율, 주소 변환 비용, 할당 유연성 사이의 선택이다.

페이지 단위로 보호하고 공유한다

페이지마다 쓰기나 실행 권한을 다르게 설정할 수 있다. 코드는 읽기와 실행을 허용하고 일부 데이터를 읽기·쓰기로 관리하는 식이다. 두 프로세스의 페이지를 같은 프레임에 연결하면 공유도 가능하다. 쓰기 전에는 같은 데이터를 함께 보다가 실제 쓰기 순간에 복사하는 방식 역시 페이지 단위 보호와 결합할 수 있다.

페이징과 스왑은 관련 있지만 같은 개념은 아니다. 페이징은 주소 공간을 나누고 연결하는 방식이며, 스왑은 어떤 페이지의 내용을 RAM 밖에 보관하는 메커니즘이다. 모든 페이지가 RAM에 있어도 페이징은 쓰인다. 파일을 필요할 때 읽는 방식이나 아직 접근하지 않은 메모리의 지연 배정도 페이지 단위 관리로 구현할 수 있다.

페이징을 이해하면 큰 배열을 한 번에 확보했다고 해서 모든 데이터가 즉시 준비되는 것은 아니라는 사실을 설명할 수 있다. 페이지 경계를 넘는 접근, 무작위 페이지 탐색, 큰 페이지 사용이 성능에 미치는 영향도 연결된다. 고정 크기 조각이라는 단순한 선택이 메모리 배치와 보호, 공유, 입출력을 하나의 관리 단위로 묶어 주는 셈이다.

참고 자료