지난 2주 동안은 project3을 진행하면서 메모리를 추상화하는 가상 메모리에 대해 알아보고, 메모리를 관리하는 기법인 MMU, 페이징과 TLB 등을 이해해보았다.
물리 주소 방식을 사용하는 컴퓨터는 다음과 같은 방식으로 데이터를 읽는다. 물리 주소가 0 ~ M-1까지 존재할 때, CPU가 물리 주소 4에서 4바이트 워드를 읽는다면, CPU는 메모리 버스를 통해 이것을 메인 메모리에 전달하고 메인 메모리는 물리 주소 4에서 시작하는 4바이트 워드를 선입하고 이것을 CPU에 돌려준다.
가상 주소 방식을 사용하는 컴퓨터에서 CPU는 가상주소(VA)를 생성하고 메인 메모리에 접근하며, 가상 주소는 메모리에 접근하기 전에 CPU chip 내의 MMU를 지나 메인 메모리에 보내질 적절한 물리 주소로 변환된다.
VM system은 가상메모리를 규정된 사이즈 블록 단위로 분할하여 관리하고, 이 분할된 블록을 가상페이지라 한다. 물리 메모리도 마찬가지로 물리페이지로 분할되어 사용된다. 가상 페이지의 집합은 unallocated, cached, uncached의 부분집합으로 나누어진다.
L1, L2, L3 → SRAM
DRAM 캐시 → 가상페이지를 메인 메모리로 캐싱하는 VM 시스템 캐시
DRAM은 SRAM보다 10배 더 느리고, 디스크보다는 100,000배 더 빠르다. 그러므로, DRAM 캐시 미스는 SRAM 캐시 미스보다는 더 값이 비싸다. 또한 디스크의 첫 바이트를 읽는 비용은 연속적인 바이트를 읽는것보다 100,000배는 느리다. 그렇기때문에 가상페이지는 4KB ~ 2MB 정도로 커지고 있다.
모든 캐시에서처럼 VM 시스템은 가상페이지가 DRAM 어딘가에 캐시되었는지 결정하기 위한 방법을 갖고 있어야 한다. 페이지 테이블이 이러한 역할을 담당하며, 페이지 테이블 엔트리(PTE, page table entry)의 배열로 구성된다. PTE가 유효 비트(valid bit)와 n bit의 주소 필드로 구성된다고 가정하자. 유효 비트는 가상 페이지가 현재 DRAM에 캐시되어 있는 지를 나타낸다. 유효 비트가 세팅되었다면(valid bit == 1) 주소 필드는 가상페이지가 캐시되어 대응되는 DRAM의 물리 페이지의 시작을 나타낸다. 만약 세팅되어있지 않다면(valid bit == 0), 가상페이지가 아직 할당되어있지 않는 NULL값 혹은 가상 페이지의 시작 부분을 가르키는 주소값을 가지고 있다.
위의 그림은 page table 1, 2, 4, 7 PTE는 physical memory를 3, 6 PTE는 disk의 가상 메모리를 가르키고 있고 0, 5 PTE는 할당되어 있지 않음을 의미한다.
CPU가 DRAM에 캐시되어 있는 가상메모리의 VP2 워드를 한개 읽을 때, 주소 번역 하드웨어(address translation hardware)는 가상 주소를 인덱스로 사용하여 PTE2를 찾고, 이것을 메모리에서 읽는다. 유효 비트가 세트되어 있기 때문에 VP 2가 메모리에 캐시되어 있음을 의미하고, PTE 내의 물리 메모리 주소를 사용해서 물리 메모리의 데이터에 접근한다.
만약 CPU가 VP3의 시작 비트에 접근하려고 할때, 미스가 발생하는데 이를 page fault라고 한다. 주소 번역 하드웨어는 메모리로부터 PTE3을 읽고, 유효 비트가 unvalid(0)임을 확인하고 page fault를 유발한다. page fault exception이 발생하면 물리 메모리에 올라가 있는 페이지중 희생할 페이지 하나를 선택한다. 만약 VP4를 희생 페이지로 정했다고 하자, VP4가 수정되었다면 데이터를 디스크에 복사하고 PTE4의 유효 비트를 0으로 바꾼다. 그 후 VP3를 디스크에서 물리 메모리에 올린다. 이때 페이지가 디스크에서 DRAM으로 옮겨지는 것을 swap in, DRAM에서 디스크로 옮겨지는 것은 swap out이라 한다.
위에 예제에서 VP5는 공간이 할당되어 있지 않은 상태이다. 이때 malloc과 같은 함수로 디스크상에 VP5를 위한 공간을 만들고 PTE5를 새롭게 만든 페이지를 가르키도록하면 페이지가 할당된다고 한다.
실제 운영체제는 각 프로세스마다 별도의 페이지 테이블을 제공하며, 별도의 가상 주소공간을 제공한다. 그 과정에서 다수의 가상페이지들이 동일한 공유된 물리페이지에 매핑될 수 있다. demend page와 virtual address space의 조합은 메모리가 시스템에서 사용되고 관리되는 방식에 중요한 영향을 준다. 특히 VM은 링킹, 로딩, 코드와 데이터 공유, application에 메모리 할당들을 단순화한다.
모든 현대 컴퓨터 시스템은 운영체제가 메모리 시스템에 접근하는 것을 제어할 수 있는 수단을 제공한다. PTE에 허가 비트를 추가해서 주소 변역 하드웨어가 가상페이지 내용으로의 접근을 제어하는 방식을 사용한다. 예를 들어, kernel mode인지 user mode인지를 파악하는 SUP비트나, 페이지에 대한 읽기와 쓰기가 가능한지 파악하는 READ, WRITE 비트를 추가하여 프로세스의 페이지 제어 가능 여부를 파악한다.
주소 번역은 N-원소 가상 주소공간(VAS, virtual address space)와 M-원소 물리 주소공간(PAS, physical address space)의 원소들 간의 매핑이다.
위 그림은 MMU가 매핑을 하기 위해 페이지 테이블을 어떻게 사용하는지를 보여준다. CPU 내에 있는 제어 레지스터인 페이지 테이블 베이스 레지스터(Page table base register)는 현재 페이지 테이블의 시작 지점을 가리킨다. n 비트 가상 주소는 p 비트 가상 페이지 오프셋(VPO, virtua; page offset)과 (n - p) 비트 가상페이지 번호(VPN, virtual page number)를 가진다. MMU는 VPN을 사용해서 적합한 PTE를 선택한다. 대응되는 물리 주소는 페이지 테이블 엔트리에서 가져온 물리페이지 번호(PPN, physical page number)와 VPO를 연결한 것이다. 이때 PPO과 VPO는 동일한 p 바이트이므로 둘은 동일하다.
위 그림은 page hit가 발생했을 때 CPU 하드웨어가 수행하는 단계를 보여준다.
위 그림은 page fault가 발생했을 경우 하드웨어와 운영체제 커널이 수행하는 단계를 보여준다.
TLB(translation lookaside buffer)는 작은 가상주소지정 캐시로, 각 라인은 하나의 PTE로 구성된 하나의 블록을 저장한다. 만약 TLB가 2^t개의 집합을 가진다면, TLB index는 t개의 최소 중요 비트로 구성되고, VPN의 나머지 비트로 이루어진 TLB tag로 구성된다.
위의 그림은 TLB hit가 발생했을 때 수행되는 단계를 보여준다.
TLB miss가 발생하면, 위에 단계에서 MMU는 PTE를 L1 캐시에서 가져와 TLB에 저장하는 과정이 추가된다.
지금까지는 시스템이 주소를 번역하기 위해서 한 개의 페이지 테이블을 사용한다고 가정해왔다. 그러나 32비트 주소공간, 4KB 페이지, 4바이트 PTE인 경우, application이 작은 크기의 가상 주소공간만 참조하는 경우에도 메모리에 항상 4MB 페이지 테이블을 필요로하게 된다.
4바이트 페이지 테이블 엔트리를 갖는 4 KB 페이지로 나누어진 32비트 가상 주소공간에 대해 생각해보자. 또한 이 시점에서 가상 주소공간이 위의 그림과 같이 2K 메모리 페이지는 코드와 데이터에 할당되고, 다음 6K 페이지는 미할당 상태이며, 다음 1023개의 페이지들 또한 미할당 상태, 다음 페이지는 사용자 스택에 할당되었다.
1단계 테이블의 각 PTE는 4M의 가상 주소 공간 크기를 매핑하는 역할을 하며, 이들 각각의 블록은 2^10개의 연속적인 페이지들로 구성된다. 예를 들어, PTE 0는 첫 번째 블록을, PTE 1은 다음 블록을 맵핑한다. 만약 chuck i 안의 모든 페이지들이 할당되지 않았다면 level 1 PTE i 는 null이다. 그러나 만약 하나의 페이지라도 할당되었다면, level 1 PTE i 는 level 2 페이지 테이블의 베이스를 가르킨다. 예를 들어, 블록 0, 1, 8의 일 부분이 할당되었고, 이들의 1단계 PTE는 2단계 페이지 테이블을 가리킨다.
2단계 페이지 테이블 내의 각 PTE들은 4KB 가상메모리 페이지를 관리하며, 이것은 앞에서 단일 레벨 페이지 테이블을 살펴보았을 때와 동일하다.
이 기법은 메모리 요구량을 두 가지 방법으로 줄여준다. 첫째는 만일 1단계 테이블의 PTE가 null이면, 해당 2단계 페이지 테이블이 존재할 필요가 없어진다. 둘째는 1단계 테이블만이 항상 메인 메모리에 있을 필요가 있다는 것이다. 2단계 페이지 테이블은 이들이 필요할 때 VM 시스템에 의해서 생성되고, 페이지 인 또는 아웃될 수 있으며, 이로 인해 메인 메모리로의 압박을 줄일 수 있다.
멀티 레벨 페이징을 이용하는 것은 비실용적이고 값비싼 것처럼 보일지 모르지만, TLB 덕분에 단일 레벨 페이지 테이블을 이용하는 것에 비해 많이 느려지는 편은 아니다.
리눅스는 가상메모리 영역의 내용을 디스크의 객체에 연결해서 초기화한다. 이 과정은 메모리 매핑이라고 알려져 잇으며 두 종류의 객체 중의 하나로 매핑될 수 있다.
어떤 경우 던지 일단 초기화가 되었다면 커널이 관리하는 swap file(swap space or swap area) 사이에서 swap-in or swap-out되며 관리가 된다.