CPU 가상화 부분에서, 제한적 직접 실행(LDE)에 대해서 배웠다. 중요한 순간에 운영체제가 관여하여 하드웨어를 직접 제어한다. 메모리 가상화에서도 비슷한 전략을 추구한다. 가상화를 제공하는 동시에 효율성과 제어를 모두 추구한다.
효율성을 위해 하드웨어의 자원을 사용한다. 몇새의 레지스터부터 TLB, 페이지 테이블 등 점차 복잡한 하드웨어를 사용하게 된다. 제어는 프로그램이 자기자신의 메모리 이외에 다른 메모리에 접근하지 못한다는 것을 운영체제가 보장한다는 것이다. 유연성 측면에서는 프로그래머가 원하는 대로 주소공간을 사용하고, 프로그래밍하기 쉬운 시스템을 만들기 원한다.
핵심 질문: 어떻게 효율적이고 유연하게 메모리를 가상화하는가?
우리가 다룰 기법은 하드웨어-기반 주소 변환(hardware-base address translation) 또는 주소 변환(address translation)이다. 주소 변환을 통해 명령어 반입, 탑재, 저장 등의 가상 주소를 정보가 실제로 존재하는 물리 주소로 변환한다.
하드웨어가 변환을 가속화 시키는데 도움을 주긴하지만, 하드웨어만으로는 메모리 가상화를 구현할 수 없다. 정확한 변환을 위해서 운영체제가 관여해야한다. 운영체제는 메모리의 빈 공간과 사용중인 공간을 항상 알아야 하고, 메모리의 사용을 제어, 관리한다.
이 모든 작업의 목표는 다음과 같다. 프로그램이 자신의 전용 메모리를 소유하고, 그 안에 자신의 코드와 데이터가 있다는 환상을 만드는 것이다.
메모리 가상화를 위한 첫번째 시도는 매우 간단하다.
논의를 진행하며 각 가정들이 점차 완화되고, 실제적인 메모리 가상화을 알 수 있을 것이다.
주소 변환을 구현을 위해 어떤 것이 필요할까? 왜 그런 기법이 필요할까?
void func() {
int x = 3000;
x = x + 3; // 우리가 관심있는 코드
}
다음은 메모에서 값을 탑재하고, 3을 증가시키고 다시 메모리에 저장하는 짧은 코드이다.
128: movl 0x0(\%ebx), \%eax; # 0+ebx를 eax에 저장
132: addl \$0x03, \%eax; # eax레지스터에 3을 더한다
135: movl \%eax, 0x0(\%ebx); # eax를 메모리에 다시 저장
x의 주소가 레지스터 ebx에 저장되어 있다고 가정하면, 그 값을 레지스터 eax에 넣고 eax 값을 3 증가시키고, 그 값을 다시 레지스터 ebx에 저장한다.
위 코드와 데이터가 프로세스 주소 공간에 어떻게 배치되어 있는지를 보자. 세 개의 명령어 코드는 주소 128에 위치하고, 변수 x의 값은 15KB(스택)에 위치한다.

명령어가 실행되면 다음과 같은 메모리 접근이 일어난다.
프로그램 관점에서 주소 공간은 0~16KB 이다. 프로그램이 생성하는 모든 메모리 참조는 이 범위 내에 있어야 한다. 메모리 가상화를 위해 운영체제는 프로세스를 물리 메모리 주소 0이 아닌 다른 곳에 위치시켜야 한다.
프로세스가 모르게 메모리를 다른 위치에 재배치시켜야 한다.

Base and bound 또는 동적 재배치(dyanmic relocation)이라고 한다.
CPU마다 2개의 레지스터가 필요하다. Base 레지스터와 Bound(limit) 레지스터. base 레지스터는 프로세스의 물리 주소를 저장하고, bound 레지스터는 주소 공간의 크기를 저장한다.
물리 주소는 다음과 같이 결정된다.
physcial address = virtual address + base
128: movl 0x0(%EBX) , % eax
위 명령어를 보면, PC는 128로 설정되고, 하드웨어가 명령어를 반입할 때, PC값을 base 레지스터(32KB)에 더해 32896의 물리 주소를 얻는다.
하드웨어는 프로세스가 참조하는 가상 주소를 통해 데이터가 실제로 존재하는 물리 주소로 변환한다. 이 주소의 재배치는 실행 시에 일어나고, 실행 후에도 주소 공간을 이동할 수 있어 동적 재배치라고도 불린다.
지금까지만 봤을 때는 bound 레지스터의 필요성을 못 느낄 수도 있다. 바운드 레지스터는 보호를 지원하기 위해 존재한다. 바운드보다 큰 가상 주소를 참조하게 되면 예외를 발생시키고 프로세스가 종료된다.
베이스와 바운드 레지스터 쌍은 CPU 칩 상에 존재하는 하드웨어 구조로 CPU당 1쌍 존재한다. 이렇게 주소 변환에 도움을 주는 프로세서의 일부를 MMU(memory managment unit)이라고 부른다.
주소 공간의 크기는 4KB인 프로세스가 물리 주소 16KB에 탑재되어있다고 가정하자. 물리 주소를 얻기 위해서 단순히 베이스 주소를 더해주면 된다. 다만 가상 주소가 너무 크면 폴트가 발생한다.


base and bound 방식의 가상 메모리 구현을 위해서 운영체제가 반드시 개입해야하는 중요한 세 개의 시점이 있다.

다음은 하드웨어/OS의 상호작용을 타임라인으로 보여준다. 메모리 변환은 운영체제의 개입 없이 하드웨어에서 처리된다. 프로세스가 잘못된 주소에 접근할 경우 운영체제가 개입한다.
