3 minute read

메모리 가상화

  • 일단은 왜 메모리를 가상화해야 하는지 생각해보자. 프로그램 입장에서 어떤 명령어를 실행하기 전에 매번 자신의 메모리가 충분하게 있는지 살펴보는 건 비효율적이다. 프로그램이 자신의 전용 메모리를 소유하고 그 안에 자신의 코드와 데이터가 있다는 환상을 만들어주어야 한다.
  • 하드웨어가 모든 메모리 참조를 실제 메모리 위치로 변환하여 준다. 그렇다면 하드웨어만으로 메모리 가상화를 구현할 수 있을까?
    • 하드웨어만으로는 주소 변환을 가속화 시킬 수는 있으나, 정확한 변환을 하기 위해선 운영체제의 지원이 필요하다.
    • 그 이유는 운영체제만이 메모리의 빈 공간과 사용중인 공간을 알고 있고, 메모리 사용 제어권이 있기 때문이다.
  • TLB, 멀티 레벨 페이지 테이블 및 기타 기법을 이해하기 전에 간단한 상황을 가정한다.
    1. 주소 공간의 크기가 물리 메모리 크기보다 작다.
    2. 각 주소 공간의 크기는 같다.
    
  • 운영체제는 메모리 가상화를 위해 프로세스를 물리 메모리 0이 아닌 다른 곳에 위치시키고 싶다. 단, 프로세스는 자신만의 전용 메모리를 소유하고 있다고 착각하는 환상을 만들어 주고 싶기에 가상주소는 0부터 시작한다. 이를 어떻게 재배치 할 수 있을까?

1. 정적(소프트웨어-기반) 재배치

  • 초창기 하드웨어 지원이 제공되기 전, 로더(loader)라 불리는 소프트웨어가 실행하고자 하는 실행 파일의 모든 주소를 원하는 물리 오프셋으로 변경한다.
  • 정적 재배치는 잘못된 주소를 사용하여, 다른 프로세스나 운영체제의 메모리에 불법적으로 접근할 수 있다는 위험성이 있다.
  • 또한, 추후 주소 공간을 재배치하는 것이 어렵다.

2. 동적(하드웨어-기반) 재배치(dynamic relocation)

  • 각 CPU마다 2개의 하드웨어 레지스터가 필요하다. 하나는 베이스(base)레지스터이고, 다른 하나는 바운드(bound)레지스터 혹은 한계(limit)레지스터이다.
    • 베이스 레지스터(base register): 프로그램에 의해 생성된 가상 주소를 물리 주소로 변환하는 데 사용된다.
    • 한계 레지스터(limit register): 이 가상 주소가 주소 공간의 범위 내에 있다는 것을 보장한다.
  • 프로세스에 의해 생성되는 모든 주소가 다음 방법으로 프로세서에 의해 변환된다.
    physical address = virtual address + base;
    
  • 프로세스가 생성하는 메모리 참조는 가상 주소이다. 하드웨어는 베이스 레지스터의 내용을 이 주소에 더하여 물리 주소를 생성한다. 이를 주소변환이라고 한다.
    • 이런 주소 변환에 도움을 주는 프로세서 일부를 메모리 관리 장치(memory management unit, MMU)라고 부르기도 한다.
    • 가상 주소가 너무 크거나 음수일 경우에 폴트(falut)를 일으키고 예외가 발생한다.
  • 이 주소의 재배치는 실행 시에 일어나고, 프로세스가 실행을 시작한 이후에도 주소 공간을 이동할 수 있기 때문에, 동적 재배치라고도 한다.
  • 두 레지스터를 통해 간단하고 효율적인 메모리 가상화를 제공할 수 있게 된다.

하드웨어 지원

  1. 특권모드 : 사용자 모드(user mode)프로세스가 특권 연산을 실행하는 것을 방지하기 위해 필요
  2. 베이스/바운드 레지스터 : 주소 변환과 범위 검사를 지원하기 위해 CPU 당 한 쌍의 레지스터가 필요
  3. 가상 주소를 변환하고 범위 안에 있는지 검사하는 능력 : 주소 변환과 변환 검사를 위한 회로
  4. 베이스/바운드를 갱신하기 위한 특권 명령 : 프로그램 시작 전 운영체제가 베이스와 바운드 레지스터 값을 지정할 수 있어야 함
  5. 예외 핸들러 등록을 위한 특권 명령어 : 운영체제가 예외 처리 코드를 하드웨어에게 알려줄 수 있어야 함
  6. 예외 발생 기능 : 프로세스가 특권 명령어 실행을 시도하거나 범위를 벗어난 메모리 접근 시도할 때 예외를 발생할 수 있어야 함
    • CPU는 사용자 프로그램이 바운드를 벗어난 주소로 불법적인 메모리 접근을 시도하려 한다면, 예외를 발생시킬 수 있어야 한다. 이 경우 CPU는 사용자 프로그램의 실행을 중지하고 운영체제의 예외 핸들러(exception)가 실행되도록 조치해야 한다.
    • 사용자 프로그램이 특권이 필요한 베이스와 바운드 레지스터 값을 변경하려는 시도도 마찬가지다.

운영체제 역할

  • 동적 재배치를 위해 하드웨어가 새로운 기능을 제공하는 것과 마찬가지로, 운영체제도 해야할 것들이 있다.
  • 1. 프로세스가 생성될 때 운영체제는 주소 공간이 저장될 메모리 공간을 찾아 조치를 취해야 한다.
    • 운영체제는 빈 공간 리스트(free list) 자료 구조를 검색해야 한다.
  • 2. 프로세스가 종료할 때(정상적으로든, 비정상적으로든) 프로세스가 사용하던 메모리를 회수하여 다른 프로세스나 운영체제가 사용할 수 있게 해야 한다.
    • 프로세스가 종료하면 운영체제는 종료한 프로세스의 메모리를 다시 빈 공간 리스트에 넣고 연관된 자료구조를 정리한다.
  • 3. 운영체제는 문맥 교환이 일어날 때 몇가지 추가 조치를 해야 한다.
    • 운영체제는 프로세스 전환 시에 베이스와 바운드 쌍을 저장하고 복원해야 한다.
    • 값을 저장할 때 프로세스 구조체(PCB)안에 저장해야 하며, 실행할 때도 마찬가지다.
    • 프로세스가 중단되면, 운영체제가 메모리의 현 위치에서 다른 위치로 주소 공간을 비교적 쉽게 움직일 수 있다.
      • 즉, 현재 위치에서 새 위치로 주소 공간을 복사하고, 운영체제는 PCB에 저장된 베이스 레지스터를 갱신하여 새 공간을 가리키도록 하면 된다.
  • 4. 운영체제는 예외 핸들러 또는 호출될 함수를 제공해야 한다.
    • 제한적 직접 실행의 기본적인 접근 방식을 따르고 있기에, 운영체제는 하드웨어를 적절하게 설정하고 프로세스가 CPU에서 실행할 수 있도록 한다. 프로세스가 잘못된 행동을 했을 때에만 운영체제가 개입하는 것이다.

제한된 실행 프로토콜(동적 재배치)

Screen Shot 2023-01-06 at 3 29 47 PM

동적 재배치의 문제점

1. 내부 단편화(internal fragmentation)

  • 사용하지 않는 스택과 힙 공간이 단순히 낭비되고 있다. 할당한 내부 공간 중 대부분 사용하고 있지 않음.

2. 고정 크기의 주소 공간

  • 더 많은 프로세스를 탑재할 충분한 물리 메모리가 있더라도, 고정 크기의 슬롯에 주소 공간을 배치해야 하기 때문에 내부 단편화가 발생한다.