이전 글에서 가상화와 하이퍼바이저에 대해서 알아보았다. 하이퍼바이저는 다시 가상화 방식에 따라 Full Virtualization
과 Para Virtualization
으로 분류된다.
Full Virtualization (전가상화)
Full Virtualization
은 한글로 전가상화라고 한다. 말 그대로 하드웨어를 완전히 가상화하는 방식이다. 전부 가상화하기 때문에 Guest OS가 Host 시스템과 완전히 분리되어 실행된다. 따라서 Full Virtualization 방식에서 Guest OS는 자신이 가상머신의 OS인지 인지하지 못한다.
Host 하드웨어와 Guest OS 사이에 Hypervisor가 분명 존재하나, VM 입장에서는 가상화된 하드웨어를 진짜(물리) 하드웨어로 인지하고 있기 때문에, 실제 물리 자원에 대해 요청을 보낸다고 생각하게 된다. 원래 system call
에 의해 App → Kernal → Hardware 순서로 서비스를 요청하는데, 이 과정을 하이퍼바이저 단에서 처리해 주는 것이다.
Hardware Assisted Full Virtualization
Full Virtualization을 구현하는 방법은 하드웨어 지원 가상화
라는 방법과 소프트웨어 적으로 구현
하는 방법으로 나뉜다. 사실 오늘날 전가상화는 하드웨어 지원 가상화와 동일한 개념으로 언급된다. 이 과정에 대해 자세히 살펴보자.
Dual-mode operation
(뒷 내용을 이해하기 위해 선행되어야 하는 내용이라 추가함)
먼저, OS는 Dual-mode operation(이중 동작 모드)
라는 것을 지원한다. 사용자와 OS는 시스템 자원을 공유하는데, 사용자에게 제한을 두지 않으면 사용자가 메모리 내의 주요 자원들을 망가뜨릴 수 있기 때문에 이를 보호하기 위해 마련된 장치인 것이다.
이중동작 모드는 사용자모드와 커널모드로 구성되어 있다. 사용자가 사용하는 application이 사용자모드에서 작동되다가 OS에게 시스템 요청을 하게 되는 경우, 커널모드로 바꿔 요청된 서비스를 실행한 후에 다시 사용자모드로 전환되는 구조이다.
다시 본론으로 들어와서 하드웨어 지원 가상화 방법에 대해 살펴보려 한다. 가장 대표적으로 Intel CPU에서 하드웨어 지원 가상화를 위해 VT-x를 사용하는데, 이 메커니즘을 조금 뜯어보며 Trap과 Emulation에 대해 알아보자.
Trap & Emulation
하이퍼바이저는 Root모드
에서 동작하고, 도메인은 Non-root모드
에서 동작하도록 되어 있다. Non-root 모드에서 동작하는 도메인이 특권 명령을 실행하면 Trap
이 발생하고 트랩 핸들러가 VM exit 명령을 수행해서 하이퍼바이저가 실행하도록 한다. 처리가 완료되면 다시 vm enter 명령을 통해 다시 도메인이 실행되도록 하드웨어가 명령어를 지원하는 방식인 것이다.
Hypervisor에서 이 모든 걸 다 처리해야 하고, 트랩이 발생할 때마다 에뮬레이션이 처리하는 오버헤드까지 생각하면 성능 저하가 생길 수밖에 없다.
Binary Translation
또한 Guest OS는 다양한 종류의 OS가 올라갈 수 있기에, 가상화된 하드웨어에 요청을 할 때 OS마다 인터페이스가 각기 다르다. 이런 다양한 형식을 하나의 형식으로 번역해주는 작업을 Binary Translation
이라고 한다.
당연히 Binary Translation 과정에서도 오버헤드가 발생하게 된다.
Hardware Assisted Full Virtualization vs Software Assisted Full Virtualization
하드웨어 지원 전가상화
의 경우 Trap과 Emulation을 이용하여 Guest OS의 Application이 직접 하드웨어의 리소스를 요청해 사용할 수 있는 구조이다.
반면 소프트웨어 적으로 전가상화
를 처리하는 경우 Binary Translation을 이용하여 각 단계에서 모든 명령에 대해 하나하나 다 가상화하는 방법으로 진행된다.
Para Virtualization (반가상화)
앞서 계속 언급했듯이 Full Virtualization
의 경우 거쳐야 할 단계가 많기에 오버헤드가 발생하며, 성능이 느려진다. 그래서 이를 해결하고자 Para Virtualization
이 등장했다.
Para Virtualization은 한글로 반가상화라고도 하는데, 핵심은 Hyper Call
이다. Para Virtualization에 사용되는 Guest OS는 Hyper Call이라는 인터페이스를 통해 하이퍼바이저에 직접 요청을 날린다. 방식은 사실 OS에서 Application이 커널에게 system call로 서비스를 요청하는 방식과 동일하다. 요청을 날리는 주체가 Guest OS이고, 받는 대상이 하이퍼바이저라는 점이 다를 뿐이다.
전가상화에서의 Guest OS는 자신이 Guest OS인지 모른다고 하였다. 하지만 반가상화에서는 Guest OS가 Hypervisor에 직접 Hyper Call을 날려야 하기에, 자신이 Guest OS라는 사실을 인지해야만 한다. 따라서 반가상화 하이퍼바이저에 올라가는 Guest OS는 커널을 수정하여, Guest용 OS를 따로 만들어야 한다.
예시로 Para Virtualization 이해하기
전가상화는 모든 명령어를 가상화해야 하지만, 반가상화에서는 굳이 모든 명령어를 가상화할 필요가 없다. 이러한 메커니즘과 반가상화에서는 왜 Guest OS의 커널을 수정해야 하는지 개발자 관점에서 설명을 하려 한다.
xor eax, eax # eax register 초기화
mov cr0, eax # control register 값 설정
자주 사용되는 어셈블리 명령어를 예시로 드려하는데, 어셈블리를 처음 접하는 분들을 위해 간단히 설명을 하자면... 첫 번째는 범용레지스터 중에 산술연산이나 논리연산을 수행하는 eax라는 레지스터가 있는데, xor연산으로 이 레지스터의 값을 0으로 초기화시키는 명령어이다. 두 번째는 프로세서 상태와 동작모드를 제어하는 여러가지 제어 flag를 가지는 cr0라는 레지스터에 flag 값을 설정하는 명령어이다.
첫번째 명령어는 단순하게 범용 레지스터를 초기화시키는 명령어라 가상화하지 않아도 된다. 반면 두번째 명령어는 컨트롤 레지스터의 값을 수정하는 중요한 명령어기 때문에 반드시 가상화해야 한다.
전가상화에서는 내가 Guest OS인지 모르기 때문에 모든 명령어를 가상화하게 된다. 반면 반가상화에서는 이렇게 꼭 필요한 중요한 명령어만 가상화한다. 필요한 명령어만 가상화하니까 당연히 모든 명령어를 가상화하는 전가상화 보다 성능이 좋을 수밖에 없다.
따라서 반가상화를 위해서는 중요한 명령어와 아닌 명령어를 구분할 수 있어야 하는데, 그렇기에 Guest OS의 커널의 수정이 필요한 것이다. 그리고 Guest OS가 하이퍼바이저에게 명령어를 가상화해달라고 직접 요청하는데, 이게 Hyper Call이다.
Reference
- https://m.blog.naver.com/ilikebigmac/222009981745
- http://bugsfixed.blogspot.com/2016/10/blog-post.html#full-virtualization-vs-para-virtualzation
- https://www.unixarena.com/2017/12/para-virtualization-full-virtualization-hardware-assisted-virtualization.html
- https://techdifferences.com/difference-between-full-virtualization-and-paravirtualization.html
- https://dong-co.tistory.com/47