세그멘테이션과 페이징을 설명하기 전 먼저 고전적이고 기초적인 가상주소할당방식을 이야기해야 한다.
동적 재배치 dynamic relocation 또는 베이스와 바운드 base and bound라고 불리는 방식은 베이스 레지스터와 바운드 레지스터를 이용해서 가상 주소공간을 물리 메모리에 배치한다.[^정적재배치]
64KB의 물리 메모리, 16KB의 가상 주소공간을 가진 16비트 시스템을 가정했을 때의 동적 재배치는 위 그림과 같이 표현된다.
이 때 베이스 레지스터는 재배치된 프로세스가 존재하는 시작부분의 주소인 0x8000
을 값으로 갖는다. 따라서 프로세스마다 다른 값을 갖는다.[^예시1]
0x0000
가상 주소를 갖는 코드세그먼트의 시작 부분은 0x8000
인 물리주소로 번역된다.
가상주소와 물리주소는 (가상주소)+(베이스 레지스터 값) = (물리주소)
의 관계를 가진다.
바운드 레지스터에는 프로세스 블록의 경계가 저장되어 있어 다른 영역을 침범하였는지를 검사할 때 사용한다.
[^정적재배치]: 정적 재배치는 실행파일을 로드할 때 코드 내의 모든 주소를 물리 메모리 주소로 바꾸어 놓는다. 간단하지만 보호기능이 없고 실행된 이후에는 주소 공간을 옮기는 것이 불가능해진다는 단점이 있다.
[^예시1]: 만약 그림에서 48KB 구간에 새로운 프로세스가 배치된다면 그 프로세스의 베이스 레지스터 값은 0xc000
일 것이다.
동적 재배치 방식은 간단하지만 내부 단편화가 항상 발생한다.
즉, 프로세스마다 가상주소공간의 크기만큼을 물리메모리에 할당하기 때문에, 프로세스에서 사용하지 않는 공간(특히 스택과 힙 사이 공간)이 낭비된다.
세그멘테이션은 물리 메모리의 이용률과 내부 단편화를 방지하기 위해 동적 재배치를 일반화한 방식이다.
세그멘트 segment는 가상 메모리를 구성하는 논리적 단위로, 크게 코드영역, 힙영역, 스택영역으로 볼 수 있다.
세그멘테이션은 세그멘트마다 베이스와 바운드 쌍을 갖는다. 따라서 운영체제는 각 세그멘트를 물리 메모리의 다른 위치들에 배치할 수 있다.
그러면 그림과 같이 미사용 영역이 큰 주소 공간(희소 주소 공간 sparse address space)도 스택과 힙을 각기 다른 위치에 배치하여 내부 단편화를 줄일 수 있다. [^3-2]
[^3-2]: segmentation fault은 세그멘트의 바운드를 벗어난 주소를 참조한 경우에 발생시키던 오류로부터 기원한 용어이다.
세그멘테이션에서는 내부 단편화를 해결하였지만 외부 단편화의 문제가 있다.
공간을 다양한 크기의 블록들로 나누면서 가용 공간 자체가 나뉘어 가용 블록들의 합인 공간 자체는 충분하지만 할당할 블록이 존재하지 않을 수 있다.
공간을 동일한 크기의 블록들로 나누는 방식이 외부 단편화의 해결책이 될 수 있으며 이를 페이징이라고 한다.
페이징에서는 주소 공간을 논리 세그멘트로 나누지 않고 동일한 크기의 페이지로 나눈다.
주소공간을 나눈 페이지를 할당할 물리 메모리 또한 같은 크기로 나누어야 하는데 이 조각을 페이지 프레임(또는 그냥 프레임)이라고 한다.
페이징은 세그멘테이션에 비해 여러 장점을 가지고 있다.
IA-32(x86)에서는 세그멘테이션과 페이징기법을 혼용해서 사용하였다.
세그멘트별로 분리된 논리주소를 선형주소로 변환하고, 선형주소를 페이징을 이용해서 물리 주소로 변환하였다.
그러나 리눅스, 윈도우 등 현대 운영체제는 세그멘트별 베이스를 0으로 설정함으로써 대체로 페이징만을 주로 사용하였다.
페이징이 더 단순한 메모리 관리가 가능하고, 페이징으로도 세그멘테이션의 메모리 보호 등을 구현할 수 있어졌기 때문이다.
또한 64비트 시스템에 이르면서 물리 메모리 공간에 여유가 생기면서 더더욱 세그멘테이션의 필요성이 작아져 x86-64에서는 세그멘테이션이 거의 비활성화 되어있다.
[^IA-32e][^IA-32e]: IA-32의 64비트 주소 공간 확장 모드
지금까지 핀토스에서는 모든 메모리 페이지를 물리 메모리에 할당하여 사용하였다.
하지만 실제 운영체제에서는 프로세스들이 사용하는 메모리의 합이 머신의 실제 물리 메모리 공간보다 큰 경우가 생길 수 있다.(프로세스가 하나인 경우에도 발생할 수 있다. 일반적으로 가상주소공간은 물리 메모리 크기보다 훨씬 더 크기 때문에..)
운영체제는 이런 상황에 대비하기 위해 페이지의 일부만 물리 메모리에 적재한다.
따라서 적재되지 않은 페이지에 접근해 page fault가 발생한 경우 페이지를 적재하게 되고, 필요한 경우 적재된 페이지 중 일부를 적재해제(교체)해야 할 수 있다.
이 교체할 페이지(victim 페이지)를 선택하는 알고리즘을 페이지 교체 알고리즘이라고 한다.
가장 기본적인 일부 알고리즘만 살펴보자면: