Early System

초기에는 컴퓨터에 대한 기대 자체가 크지 않았지만 컴퓨터의 중요성이 점차 커짐에 따라 많은 사람들이 고가의 장비인 컴퓨터를 공유해서 효율적으로 사용하고자 했습니다. 따라서 여러 프로세스를 실행할 수 있는 방법들을 생각했는데 그 중 한 가지는 프로세스가 I/O를 요청할 때 다른 프로세스를 실행하는 방법이였습니다. 이 방법을 통해 CPU utilization을 개선할 수 있었습니다.

뿐만 아니라 여러 사람들이 컴퓨터를 공유하기 시작하고 각자가 실행하는 프로세스에 대해 빠른 응답을 받기를 원했습니다. 따라서 CPU를 나눠 사용하는 시분할 개념이 등장하고 이를 구현한 초기 방법은 한 프로세스를 잠깐 실행하여 실행 중에는 모든 메모리에 대한 엑세스 권한을 부여하고 시간이 끝나면 프로세스를 중지한 후 모든 상태를 디스크에 저장하는 방식이였습니다. 디스크에 저장/복원하는 과정은 매우 느리기 때문에 디스크에 프로세스를 저장하는 대신 프로세스를 전환하는 동안 메모리에 프로세스를 남겨두어 OS가 시분할을 효과적으로 구현하도록 바뀌었습니다.

image

여러 프로세스가 메모리에 존재하고 하나의 프로세스가 실행되는동안 다른 프로세스는 대기하고 있습니다. 하지만 실행 중 모든 메모리에 대한 엑세스가 허용되므로 하나의 프로세스가 실행 중 다른 프로세스의 메모리 영역을 변경할 수도 있습니다.

The Address Space

이렇듯 물리 메모리에 대한 사용이 까다롭기 때문에 프로세스 입장에서 쉽게 물리 메모리를 사용하기 위해 등장한 개념이 Address space입니다. 예전 글에서 프로세스는 실행중인 프로그램을 OS가 추상화 한 것이라고 했고 이러한 프로세스가 사용하는 메모리를 Address space라고 합니다.

image

첫 글에서도 살펴봤지만 동일한 프로그램을 실행해 두 개의 프로세스를 실행한 후 스택의 주소를 출력하면 동일한 주소를 출력하는 것을 확인했었습니다. 이는 메모리가 가상화 되었다는 증거였지요. 하지만 두개의 프로세스의 스택 위치가 물리 메모리에서도 동일하진 않습니다. 즉 누군가는 가상화된 메모리 주소를 물리 메모리로 매핑 해주어야합니다. 이 역할을 수행하는 하드웨어가 바로 Memory Management Unit(MMU)입니다.

image

프로세스를 다시 살펴보면 예전 그림에서 주소변환정보가 추가되었습니다. 맨 처음 그림에서는 프로세스의 메모리가 연속적으로 배치되어있으므로 주소변환을 위해서 물리 메모리의 시작 주소만 파악하면 되지만 나중에 Segmentation이나 Page단위로 메모리를 관리하면 주소변환정보가 더 복잡해지게 됩니다. 이는 나중에 다시 다루도록 하겠습니다. 어쨌든 프로세스마다 주소변환정보를 가지고 있는 것은 당연하고 물리 메모리에서는 주소변환정보를 kernel space에 저장하고 있습니다.

Goals

가상화된 메모리를 다룰 때 신경써야하는 것을 무엇일까요?

첫 번째는 효율성입니다. 주소변환을 계속해야하고 소프트웨어적으로 이를 구현하면 느리므로 MMU의 도움을 받습니다. 뿐만 아니라 더욱 효율적으로 변환하기 위해 변환 내용을 기억하여 TLB라는 캐시를 사용하기도 합니다.

두 번째는 격리입니다. 메모리에 여러 프로세스가 실행되는 만큼 각 프로세스마다 격리가 이루어져야합니다. 이 내용은 CPU의 user mode와 kernel mode를 통해 가능하다는 것을 살펴본 바 있습니다.

마지막은 투명성입니다. 프로그램은 자신이 가상화된 사실조차 모른 채 실행이 되어야합니다. 실제로 하드디스크에 Address space 내용들이 저장되어있고 내용 중 일부만 메모리에 올라와서 실행됩니다. 필요에 따라 하드디스크에 저장된 내용이 메모리에 올라와야할 때도 있는데 프로그래머는 이러한 메모리 관리에 대해 신경쓰지 않고 단순하게 프로그램을 작성하는 것입니다. 투명성이라는 단어 때문에 모든 과정이 노출되어야한다 라고 생각할 수도 있지만 실제로는 그 반대임을 명심합시다.