[유혁 교수의 운영체제] 3.운영체제 구조

운영체제 구조

System Structure

  • 운영체제는 규모가 매우 크고 복잡한 소프트웨어
    • 설계 시 소프트웨어의 구조를 신중히 고려해야 함
  • 좋은 설계를 통해 쉬워지는 것들
    • 개발(Develop)
    • 수정(Modify and Debug)
    • 유지 보수(Maintain)
    • 확장(Extend)
  • 디자인 목표 중에 좋은 것이란?
    • 좋은 다자인에 대한 기준이 절대적이지 않으며, 이는 설계하고자 하는 시스템의 용도와 관계가 있다.

OS Design Principle

  • Mechanism
    • Determine how to do something
      • 어떻게 할 것인가?
    • Ex : concrete alogorithms, data structures
  • Policy
    • Decide what to be done
      • 무엇이 되게 할 것인가?
    • High level direction
      • 네트워크 패킷과 파일 데이터 처리 Priority (예전에는 배치 시스템을 먼저 돌렸으나, 요즘에는 사용자가 작업중인 어플리케이션을 우선으로 작업을 수행시킨다.)
      • use mechanism
  • Mechanism과 Policy를 분리함으로써 운영체제 설계를 보다 module화 할 수 있음
    • 규모가 아주 큰 OS를 설계할 때에는 어떤 Mechanism과 Policy를 선택할지 염두에 두면서 큰 소프트웨어를 작은 모듈들로 쪼개는 것이 중요하다.
    • 모듈화의 예시 - layering

Layering

  • OS의 복잡도를 낮추기 위한 방안
  • Layer는 정의가 명확한(well-defined) 함수들로 이루어짐
    • 용도와 목적이 분명히 정의된 함수들로 이뤄져 있다.
  • 하나의 Layer는 인접한 Layer와만 통신
    • 위, 아래에 인접한 layer만과 통신하며 2단계 이상 건너띈 layer와는 직접적으로 통신하지 않음
      • 여기서 통신이란 넓게는 메시지를 주고 받는 의사소통을 의미하기도 하지만, 여기서는 호출 가능 여부를 말한다.
      • 2단계 이상 건너띈 layer와 직접 통신이 불가능하므로, 설계의 복잡도가 낮아진다.
        • 밑의 그림에서 B 모듈을 D 모듈로 바꾼다고 할 때, D가 A와 C가 요구하는 인터페이스와 시멘틱스(Semantics)를 잘 맞춰주기만 해도 B를 완벽히 대체할 만한 조건을 갖출 수 있다.
        • 각 모듈 사이의 결합도가 낮다.
  • 설계의 복잡도를 낮출 수는 있으나, 그로 인해서 overhead가 발생함
    • 굳이 거치치 않아도 되는 계층이 있다해도 반드시 이 계층을 지나가도록 설계될 경우 overhead가 발생한다.
    • overhead가 너무 커질 경우, design principle을 일부 무시하고, 계층을 건너띌 수 있도록 설계하기도 한다.
    • -> 복잡도와 overhead 사이의 trade-off를 계산하여 principle을 엄격히 따를 것인지 아닌지 여부를 결정한다.
  • ex) 7-layers of the OSI model

Interface에서 Syntax와 Semantics

  • Syntax - 문법
    • 함수의 데이터 타입, Array의 크기, Arguements의 개수 등
  • Semantics - 의미
    • 함수의 용도, 동작

Layering vs Modularity

  • Modularity
    • 여러 개의 함수를 묶은 모듈들을 병렬적으로 나열한 후, 각 모듈 사이의 인터페이스를 통해서 서로 통신할 수 있도록 설계된 구조
    • 각 모듈 사이의 접점(인터페이스)이 arbitrary하고, 넓다. 즉, 모든 모듈은 어느 모듈이든 서로 호출이 가능하며, 이 인터페이스가 표준화되어있지 않다.
    • 접점이 넓을수록 보안에 취약할 가능성이 크며, 표준화되어 있지도 않기 때문에 버그를 찾기도 힘들 수 있다.
    • ex) process management, memory management - 이런 모듈들은 서로 간의 결합도가 높고, 각 모듈의 abstraction 정도가 높아, Layering을 적용하기가 힘들다.
  • Layering의 장점
    • Modularity보다 표준화(common)된 인터페이스 설계
    • abstraction 정도가 낮은 네트워크에서 주로 사용된다. 코드를 단계별로 엄격하게 stacking을 하기 수월하기 때문이다.
    • Layer의 수정이 다른 layer와 독립적임

불완전한 Layering

  • Layering 원칙을 지키지 않은 예시 : MS-DOS
    • Application이 BIOS를 직접 호출할 수 있도록 했다. 즉, 어플리케이션이 임의로 시스템을 fail시킬 수 있었다는 것이다.
  • Layering 원칙을 지킨 예시 어떤 경우에서도 어플리케이션이 커널을 crash해서는 안된다. 커널과 어플리케이션 사이에는 큰 barrier를 두고 Layering을 시키는 principle이 도입되어야만 완전한 Layering이라고 할 수 있다.

Kernel 내의 모듈들

  • 커널 내의 시스템들은 모두 아래 그림과 같이 모듈화되어있다.
  • 각 모듈들은 하드웨어와 연결되기 위한 인터페이스를 갖고 있다.
    • ex) DKI(Device Kernel Interface), HAL(Hardware Abstraction Layer)
      • HAL에 관한 설명은 다음 글 참조 https://hee-jin506.github.io/os/2021/04/04/OS-HAL.html
    • 인터페이스가 필요한 이유 : 하드웨어와 OS를 분리하여 하드웨어의 종류와 상관없이 OS가 하드웨어를 안정적으로 운영할 수 있어야 하기 때문
      • 인터페이스가 잘 지원되지 않았을 때에는 하드웨어를 바꿀 때마다 커널을 다시 컴파일하거나 해당 하드웨어를 지원하는 OS의 버전을 찾아야 했다. 인터페이스의 Syntax와 Semantics가 모두 공개되어 그것에 맞게 프로그래밍만 하면 어떤 하드웨어 위에서도 OS가 돌아갈 수 있게 된 것은 90년대 후반부터였다.

CPU의 실행 모드(mode)

MS-DOS가 불완전한 Layering을 설계한 것은 경로를 단축하여 지름길을 내준 것도 있지만, 한편으로는 하드웨어 기술이 CPU의 실행모드를 구분하지 못했기 때문도 있다. 사용자(application)와 kernel이 서로 다른 권한(privilege execution)을 가지지 않는다면, 중간 계층에서 아무리 막으려고 해도 어플리케이션은 얼마든지 커널로 점프가 가능했다는 것이다. 커널은 하드웨어에 대한 접근이 가능한 시스템이니만큼, 어플리케이션은 절대로 직접적으로 커널로 점프할 수 없도록 막아야 했다. 따라서 운영체제와 어플리케이션의 권한을 나눠야한다는 결론에 도달했다. 이전까지는 CPU는 연산 같은 단순한 기능을 하는 수행 모드 하나만 갖고 있었으나, 현재는 최소한 두가지 이상, 많게는 7개까지 다양한 실행 모드를 갖는다.

  • CPU의 2가지 이상의 실행 모드
    • System protection을 위해서 필요
      • 실행 모드의 권한에 따라 접근할 수 있는 메모리, 실행 가능한 명령어가 제한됨
        • 멀티프로그래밍에서의 스위칭을 어플리케이션이 할 수 있도록 한다면?
    • 각각의 모드 별로 권한(privilege)이 설정됨
    • Hardware 지원이 필요
      • Intel: ring 0~3
        • Kernel - ring 0, app - ring 3

User mode와 kernel mode 비교

다양한 CPU의 실행모드가 존재하지만 크게는 User mode와 kernel mode로 나뉠 수 있다.

  • Kernel mode
    • 모든 권한을 가진 실행 모드
    • 운영체제가 실행되는 모드
    • Privilege 명령어 실행 및 레지스터 접근 가능
      • ex) I/O 장치 제어 명령어, memory management register - CR3
  • User mode
    • Kernel 모드에 비해 낮은 권한의 실행 모드
    • 어플리케이션이 실행되는 모드
    • Privilege 명령어 실행은 불가능 - 하드웨어적으로 막혀있다.
      • 네트워크도 하드웨어, 즉 자원이라고 할 수 있는데, 이 네트워크를 사용할 때에도 커널 모드에서만 사용이 가능하므로 어플리케이션이 인터넷에 연결되려고 할 때마다 스위칭이 필요하다.
  • 실행 모드 전환(execution mode switch) - 멀티프로그래밍에서 다룬 스위칭과는 상이한 개념
    • CPU의 실행 모드 설정은 시스템 보호가 목적
    • User mode에서 실행 중인 어플리케이션이 Kernel mode의 권한을 필요로 하는 서비스를 받을 방법을 고안해야 한다. => 시스템 콜

Q : 교수님 그러면 cpu가 kernel mode로 작동하다가 user mode로 작동하는 것을 반복하는 것인가요 아니면 cpu의 일부분은 kernel mode로 할당되어 작동하고 다른 일부분은 user mode로 할당되어 작동하는 것인가요? A : 간단하게는 CPU 전체의 실행모드가 전환된다고 생각하는 것이 좋다. 그러나 나중에는 context 안에서는 개념을 배우게 될텐데, 엄밀히는 하나의 context 안에서 실행모드가 전환된다고 하는 것이 옳다.

System Call

  • User mode에서 Kernel mode로 진입하기 위한 통로
    • 커널에서 제공하는 protected 서비스를 이용하기 위하여 필요
      • Open(2) : a file or device ‘(2)’이 붙는 이유 - Open이 명령어일 수도, 라이브러리일 수도 있는데 이것이 명령어임을 특정하기 위함이다.
      • Write(2) : to file or device
      • Msgsnd(2) : send a message
      • Shm(2) : attach shared memory

System Call의 동작 원리

  1. Application이 Open(2)를 호출하면

  2. CPU가 User mode에서 Kernel mode로 진입하고
  3. Open 명령어에 해당하는 인덱스 번호를 통해 시스템 콜 테이블에서 open()이라고 하는 커널 내부 함수를 찾는다.
  4. 이 함수를 실행하고 실행이 완료되면 다시 User mode로 돌아간다.

이것을 좀 더 자세히 살펴보자.

System Call : Arguement 처리

커널 내부 함수란 커널이 갖고 있는 함수며, 이용자가 임의로 정의할 수 없다. 이 함수가 특정 Arguement를 필요로 할 시, User program은 이 특정 값을 CPU Register에 실어서 보낸다. System Call Semantic/System Call Convention을 통해서 어느 Register를 써야할지는 모두 결정이 되어있으며 프로세스마다, CPU마다 다르다.

User Program이 store X라는 System Call을 호출하려고 한다.

  1. User Program 이에 해당하는 Arguement 값이 있으면 Register에 넣고 store X를 호출한다.
  2. CPU Mode 전환이 발생하면서 커널에서 Register를 통해 값을 받고 함수를 수행한다.
  3. 커널에서 함수가 완료되면 결과를 Register에 넣어 User Program에 돌려준다.

Register의 크기가 제한되어있는데 Arguement 값의 크기가 이를 넘어간다면, Stack에 Arguement를 실어서 보낸다. 즉, Register에 보낼 수 있는 만큼을 보내고 나머지는 정해진 메모리(Stack)를 통해 커널에 넘겨줄 수가 있는 것이다.

System Call의 예

다음 목록을 확인해보면 Unix와 Windows의 System Call들 중 많은 것들이 이름은 서로 다르지만 같은 기능을 하고 있음을 알 수 있다. 비록 운영체제가 달라도 필요한 System Call들은 비슷하다는 의미이다.

각 운영체제들은 이 밖에도 아주 많은 System Call들을 갖고 있다. 이는 여러가지 방법을 통해서 자신의 컴퓨터에서 사용할 수 있는 System Call 목록을 알 수가 있을 것이다.

QnA

Q : user 모드에서 실행할 수 없는 instruction이 hardware적으로 거부된다고 말씀하셨는데 어떤 방식으로 mode가 식별되어 이런 과정이 진행 되는것인지 궁금합니다. A : Mode Switching을 initiate하는 instruction을 Mode Switch Instruction라고 한다. 운영체제가 이 Instruction을 수행해서 Switching을 하게 된다.

Q : Mode Swtiching의 권한을 허용하는 주체는 User인가요? A : 아니다. Switching은 하드웨어에서 우선적으로 이뤄진 후, 그 다음부터의 모든 Control은 OS가 하게 된다. 이 Control에는 보안 체크도 포함한다.

일반적인 커널의 구조

  • System Call - Application이 Kernel Service을 호출하기 위한 중간 매개체
  • Kernel Interface to the Hardware - Kernel이 하드웨어를 사용하기 위한 중간 매개체 역할을 하는 인터페이스
    • ex) HAL(https://hee-jin506.github.io/os/2021/04/04/OS-HAL.html)

Kernel Architecture

  • Monolitihic Kernel
    • 우리가 흔히 사용하는 일반적인 운영체제는 모두 이에 해당
    • ex) 윈도우, 리눅스
  • MicroKernel
  • Hypervisor
    • Xen
    • KVM과 Container

Monolithic Kernel

특징

  • 커널이 사용자와 같은 주소 공간에 위치
    • ‘Mono’ - 하나 또는 동일한, ‘Lithic’ - 덩어리
    • 커널과 사용자가 한 덩어리로 묶이는 구조
  • 주소 공간을 커널 코드와 사용자가 나누어서 사용
  • 커널 코드는 한 “덩어리”로 구성됨
    • 커널은 시스템 콜을 통하여 접근

그림을 살펴보면 네 개의 프로그램이 수행되고 있고, 각 프로그램의 주소 공간이 애플리케이션이 차지하는 공간과 커널이 차지하는 공간으로 나뉜다. 왼쪽에 쓰인 0G, 3G, 4G는 통신속도를 의미하는 것이 아니라, 주소 공간 총 4GB 중에서 어플리케이션이 3GB을 차지하고, 커널이 1GB을 차지함을 의미하는 것이다.

Monolithic Kernel 장단점

  • 장점
    • 어플리케이션과 모든 커널 서비스가 같은 주소 공간에 위치하므로, 시스템 콜 및 커널 서비스 간의 데이터 전달 시, 오버헤드가 적음
      • 시스템 콜을 통해 어셈블리로 된 instruction을 수행하는 과정 자체가 비용이 적게 드는 통신 방법이라고 할 수 있다.
    • 우리가 현재 알고 있는 운영체제가 대부분 모놀리틱 커널인 이유는 대부분 탁월한 성능 때문이다.
      • 운영체제에서 성능은 가장 중요한 사용 기준이 된다.
  • 단점
    • 모든 서비스 모듈이 하나의 바이너리로 이루어져 있기 때문에 일부분의 수정이 전체에 영향을 미침
    • 각 모듈이 유기적으로 연결되어 있기 때문에 커널 크기가 커질수록 유지 보수가 어려움
      • 기능 확장을 하게 될 경우, 관련된 모든 모듈이 수정되어야 한다.
    • 한 모듈의 버그가 시스템 전체에 영향을 끼침
      • 여기서 의미하는 버그는 우리가 익히 아는 버그는 아니다. 그러한 버그는 이미 운영체제가 배포되는 시점에서 대부분 해결된 상태일 것이다. 여기에서 버그는 보안상의 취약점이 될 수 있는 지점을 말한다. (모놀리틱 커널에서 가장 1차적인 Attack Service는 System Call이다. 이 취약점을 보완하기 위해 특정 System Call은 커널에서 필터링을 통해 안받도록 하는 구조를 취하고 있다.)
      • 이 버그로 인해 해커가 취약점을 파고든다면, 운영체제 전체를 컨트롤할 수 있는 가능성도 생긴다.

MicroKernel

모놀리틱 커널의 다양한 문제(디버깅의 어려움, 보안의 취약성 등)를 해결하기 위해 굉장히 오랜 시간 연구되었다.

  • 특징
    • 커널 서비스를 기능에 따라 모듈화하여 각각 독립된 주소 공간에서 실행
    • 이러한 모듈을 커널 서버라고 하며, 서버들은 독립된 주소 공간으로 구현
      • 서버들의 공통적인 기능만 한 통일된 공간에 남겨둠
    • 마이크로 커널은 서버들 간의 통신(IPC), 어플리케이션의 서비스 콜 전달과 같은 단순한 기능만을 제공

Monolithic Kernel과 Microkernel

  • Monolithic Kernel : 여러개의 어플리케이션이 하나의 큰 커널 공간에 붙는 구조
  • Microkernel : 커널 공간이 기능별로 여러 서버로 분리되며, 각 서버는 공통 기능을 수행하는 마이크로 커널 위에서 동작한다. 사용자(어플리케이션)는 자신이 사용하는 커널이 쪼개진 서버인지 하나의 통일된 커널인지 구분할 수 없다.

Microkernel의 장단점

  • 장점
    • 각 커널 서비스 서버가 따로 구현되어 있기 때문에 서로 간의 의존성이 낮음
      • Monolithic 커널보다 독립적인 개발이 가능
        • 각 서버를 인터페이스만 준수하여 따로 개발 가능
      • 커널의 개발 및 유지 보수가 상대적으로 용이
    • 커널 서비스 서버의 선택적인 재시작/종료 가능
      • 하나의 커널 서버에 문제가 발생할 경우, 그 서버만 리부트가 가능하다.
      • 불필요한 서비스의 서버는 종료
        • 필요하지 않는 커널 서버는 그냥 메모리에서 내려버릴 수가 있다.
        • 많은 메모리 및 CPU utilization 확보 가능
    • 이론적으로 Micro 커널이 Monolithic보다 안정적
      • 외부에서 공격을 받아도 영향을 받는 면이 Monolithic보다 훨씬 적다.
        • 커널 서버가 분리되어 있기 때문에, 해킹을 당하더라도 Control될 수 있는 커널의 영역이 Monolithic보다 적다.
        • 보안 취약점인 System Call의 개수가 Monolithic보다 훨씬 적다.
      • 문제 있는 서비스는 서버를 재시작하여 해결
        • Monolithic은 커널에서 문제가 생기면 커널 전체를 다운시켜야 한다.
    • 서버 코드가 protected memory에서 실행되므로 검증된 SW 분야에서 적합함
      • 서버 코드를 쪼개서 관리하기 때문에, 안정성이 크므로 검증된 SW 분야에 적합하다.
      • 임베디드 로봇 산업, 의료 컴퓨터 분야
  • 단점
    • Monolithic 커널보다 낮은 성능을 보임
      • 독립된 서버들 간의 통신 및 Context Switching
        • 커널 서버들은 서로 Message Passing을 통해 서로 통신하는데, 이것이 마이크로 커널의 성능저하 요인이 된다.
      • L4 마이크로 커널은 하드웨어를 활용하여 성능 개선
        • 독일에서 만든 시스템으로 하드웨어의 기능을 잘 활용하면 성능이 리눅스와 비슷한 수준까지 발전할 수 있음을 논문을 통해서 보였다.
        • 커널 서버들이 Message Passing이 아닌 하드웨어의 클락을 통해서 통신함으로써 성능 저하를 개선하는 방법을 취한다.

Message Passing of Microkernel

마이크로커널은 커널 서버 사이에서 Message Passing을 통해 서로 통신한다. 이 Message Passing 과정은 시간이 어느정도 걸릴 수 밖에 없다.

블록 I/O 처리 비교

마이크로커널의 성능이 모놀리틱 커널보다 좋지 않은 이유를 블록 I/O 처리 과정을 통해 좀 더 구체적으로 들여다보자. 아래 그림에서 헷갈리지 말아야할 부분은 마이크로 커널 그림에서 Kernel 박스로 표현된 영역은 마이크로 커널을 의미한다. 마이크로 커널만을 커널로 표현하고, 나머지 그 위에서 돌아가는 별도의 커널 서버들은 User Space에 옮겨진 것이다. 따라서 각 모듈들이 마이크로 커널을 System Call을 통해 호출하고, 마이크로 커널은 각 모듈을 Upcall을 통해 호출한다. (위의 그림에서 커널 공간에서 커널 서버들이 존재한다고 설명했는데, 이는 실질적으로 테스트를 하거나 할 때에는 커널 공간에 넣어서 테스트하기 때문)

  • Monolithic Kernel : Application이 System Call을 통해 I/O 커널 서비스를 호출하면 커널 안에 있는 모듈들이 VFS, EXT3, Device driver 순으로 단순 함수 호출(검은색 화살표로 표시됨)되어 커널이 결국 Disk라는 하드웨어를 control할 수 있게 된다. 커널이 I/O 과정을 완료하면 함수가 동기적(synchronous - 단순한 함수 호출이 완료되어 클라이언트에게 다시 리턴되는 형태)으로 리턴된다. 각 모듈들이 커널 공간에 안에 존재하는 이유는 Application이 마음대로 커널 서비스를 사용하지 못하도록 한 번 더 커널 공간으로 감쌌기 때문이다.
  • Microkernel : 커널 안에 있던 각 모듈들이 User Space에서 독립된 모듈로 존재하며, Application이 System Call을 통해서 I/O 커널 서비스를 호출하면 (마이크로) 커널 안에 있는 IPC모듈이 바깥에 있는 VFS와 EXT3에 대해서 차례로 요청과 응답을 받게 된다. 마지막으로 Device Driver에 요청하면 이 모듈이 Disk를 직접 Control한다. 요점은, 커널 안에서 각 모듈들이 함수 호출을 하는 것이 아니라 별도의 주소 공간에 위치하는 모듈들이 서로 메시지를 주고 받으면서 동작한다는 점이다. 같은 주소 공간에 있지 않는 이상 함수 호출이 불가능하기 때문에 여러번의 Message Passing 과정이 발생하고 이 지점들에서 성능 저하가 발생한다.
    • 좀 더 구체적으로 살펴보자. Monolithic과 다르게 Microkernel에서는 커널에서 User program으로 무언가를 요청(invoke )하는 지점이 존재한다. 그림에서 초록색 선에 해당하는 upcall이다. Upcall이 익숙하지 않을 수 밖에 없는 이유는 Monolithic에는 거의 발생하지 않는 일이기 때문이다.
    • 커널 서버를 커널 공간으로 감싸지 않았다고 해서 Monolithic보다 각 커널 서버들이 보호가 되지 않는 것이 아니며, Monolithic과는 다른 방법으로 보안 처리가 된 것이다.
      • 은근 피셜 - 어차피 Application이 호출하면 가장 우선적으로 요청이 커널 공간을 거치기 때문에 이것도 각 커널 서버를 보호하고 있다고 볼 수 있지 않을까?
    • Synchronous? : Application에서 커널 서비스를 호출한 후에 바로 다른 작업으로 넘어간다면 비동기이고, I/O 과정이 모두 완료될 때까지 기다리고 있다면 동기인 것인데, 많은 경우에는 Application이 그 긴 과정을 기다리지 않기 때문에 비동기라고 할 수 있다.

Q : 마이크로 커널에서 커널 서비스들이 유저 공간에 있다는 것은 일반 프로세스들처럼 커널 서비스들도 스위칭을 한다는 것인가요? A : 그렇다. 그림에서 보는 것처럼 System Call을 통해서 스위칭 과정을 거친다.

Q : 시스템 콜 호출할때 argument를 레지스터로 전달하는 것처럼 microkernel의 커널 모듈사이에 message passing도 레지스터를 사용하나요? A : 그렇다.

Q : 다른 address space를 이용한다는 것은 application, VFS, EXT3, device driver가 각각의 virtual space를사용한다는 의미인가요? A : 그렇다. 그러나 아직 virtual space 개념을 배우지 않았기 때문에 이 질문에 대해서 아직 깊이 고민하지 않아도 된다.

Q : 마이크로 커널에서 파일 서버, 디바이스 드라이버를 포함한 커널 서비스가 커널 공간에 있다고 나와있는데 유저 공간에서 스위칭이 일어난다는 것이 어떤 의미인지 모르겠습니다. 커널 공간에서도 스위칭이 가능한 것인가요? A : 정확히는 여러 개의 커널 서버가 User Space로 보내진 것이다. 따라서 User Space에 있는 커널 서비스가 (마이크로) 커널로 진입하려면 스위칭이 발생하는 것이다. 이렇게 된 이유는 Device Driver를 모두 커널에 넣다보니까 보안에 취약하게 되고, 커널 전체가 불안정적인 문제가 발생하여 이것을 User의 level로 보냄으로써 이 문제를 보완하려고 한 것이다.

Q : Monolithic과 Microkernel 모두 Application과 kernel이 메모리에 올라가있다고 생각해도 될까요? A : 그렇다. 누가 어떻게 메모리에 올라가는 지에 관해서는 Memory Management 파트에서 배우게 될 것이다.

가상화(virtualization)

가상화 기술이 발전하기 전까지는 하드웨어와 OS가 1:1로 존재했고, OS가 죽으면 하드웨어를 사용하지 못했다. 그런데 가상화 기술을 통해 Hypervisor Layer를 하드웨어 위에 올려놓고 그 위에다가 2개 이상의 OS를 올릴 수 있게 되었다. 즉, 하드웨어를 Hypervisor가 관리하게 함으로써 하드웨어와 OS를 분리할 수 있게 된 것이다. 이 Layer 위에 올라가는 OS들을 Hypervisor 역할을 하는 OS와 구별하기 위해 GuestOS라고 칭한다. 우리가 윈도우 위에서 가상화를 통해 리눅스를 동시에 동작시킨다면 Hypervisor는 윈도우, GuestOS는 리눅스이다.

어플리케이션의 관점에서 보면, GuestOS는 Application에게 Virtual Machine을 제공하는 것이다. 리눅스에서만 돌아가지 않는 어플리케이션을 윈도우용 하드웨어에서 동작시키고자 할 때에 리눅스 GuestOS를 설치해서 동작시킬 수가 있다. 이때 어플리케이션은 자신에게 버츄얼 머신을 제공하고 있는 GuestOS과만 소통하며 이 OS가 하드웨어에 올라간 전체 OS인 것처럼 착각한다.

이 가상화는 컴퓨터의 파티션을 나누어서 매번 다르게 부팅하는 듀얼 부팅과는 완전히 다르다. 한번에 하나의 OS만 동작되는 듀얼 부팅과는 다르게, 두 개의 다른 OS가 동시에 동작이 가능하기 때문이다.

  • 1960년대부터 존재했음
  • 그러나 성능 저하로 활용되지 못하였음
    • 컴퓨터 성능이 점차 발전하면서 점점 가상화 기술이 떠오르기 시작했음
  • Xen의 등장(2003년)으로 computing의 기반 기술로 자리 매김
    • Xen 관련 논문에서 가상화 환경에서의 성능을 Native(한 하드웨어 위에서 가상화없이 OS가 돌아가는 환경)에서의 성능의 97% 정도까지 끌어올릴 수 있음을 밝혔다.
    • 하이퍼바이저 계층 도입
    • GuestOS는 Linux, Windows 모두 가능
  • 특히, 클라우드의 enabling technology
    • 클라우드란? 원격에 있는 컴퓨팅 자원을 PaaS Layer를 통해 빌려서 사용할 수 있게 하는 기술
  • 5G는 네트워크 가상화를 도입함 : computing을 넘어서 네트워크까지 가상화 적용
    • 기존에는 네트워크 망을 체계없이 임의적으로 나눠사용했다면, 현재는 네트워크 가상화를 통해 namespace와 같은 체계를 정의해가면서 효율을 높이고 사용자들의 편의성을 도모하고 있다.

Q : Java 버츄얼 머신과 현재 설명하는 버츄얼 머신은 같은 개념인가요? A : Java가 그런 의도를 갖고 만들어진 것은 맞지만, 엄밀히는 둘이 다른 개념이다. Java 버츄얼 머신은 Hypervisor 위에서 돌아가는 것이 아니다. 간단히 비유하자면, OS가 Java 버츄얼 머신에 있어서 Hypervisor Layer 역할을 해주고 있다고 할 수 있다.

Q : 위의 그림만 보았을 때에는 Hypervisor Layer와 HAL 의 역할이 비슷해보인다. A : 그렇게 보일 수 있으나 둘이 완전히 다른 개념이고 Hypervisor가 HAL보다 훨씬 더 큰 개념이라고 볼 수 있다.

Virtualization Advantages

  • Consolidation
    • allow easier provisioning - 유동적인 하드웨어 자원 분배
    • reduce HW cost - 자원 낭비 X

왼쪽 그림은 가상화를 사용하지 않는 경우로, 하드웨어 하나에 OS 하나가 바인딩(1:1)되어있다. 그리고 그 OS에서 각각의 어플리케이션들이 동작하고 있다. 이러한 경우에는 OS 하나당 사용할 수 있는 하드웨어 자원들이 이미 정해져있다.

반면, 오른쪽 그림은 가상화를 사용하는 경우로, 한 하드웨어 위에 가상화 계층을 올리고, 그 위에 여러개의 OS를 올린 구조를 취한다. 이 경우에는 각 OS들이 하드웨어에서 필요한 만큼의 자원을 유동적으로 사용할 수가 있다. 즉, 가상화를 통해서 한 하드웨어를 여러 OS들이 사용하는 하나의 pool로 사용할 수 있다는 효과가 있다.

웹 서버와 같은 서비스들은 시간에 따라 필요한 자원의 양이 유동적일 수가 있는데, 가상화를 사용하지 않는다면 정해진 자원 이상으로 필요로 하게 될 경우, 복잡한 과정을 통해서 어떻게든 자원을 늘려야 한다. 이렇게 억지로 자원을 늘린다고 해도 더 이상 그 자원을 필요로 하지 않는 순간에는 자원이 낭비되는 문제가 발생한다. 따라서 하드웨어를 정해진 양으로 나눠서 사용하지 않고, 가상화를 통해서 원하는 때에 필요한 만큼의 자원만을 사용할 수 있도록 하드웨어를 provision하면 무리하여 자원을 늘릴 필요도 없고, 자원 낭비도 감소할 것이다.

More Adventages

  • Decoupling : 하드웨어와 소프트웨어의 분리
    • Eliminate Dependency between software and hardware
      • 하드웨어와 소프트웨어 사이의 의존성을 제거하면, 하드웨어에 변화가 생겨도 이에 맞춰 GuestOS 안에서 돌아가던 기존의 소프트웨어를 하드웨어에 맞게 변화시킬 필요가 없다.
        • 소프트웨어 코드의 변동은 버그를 발생시킬 수 있으므로 안정성에 큰 영향을 준다.
        • 기술의 발전으로 계속해서 하드웨어를 발전시키더라도 이미 검증된 소프트웨어를 아무런 변동 없이 사용할 수 있기 때문에 소프트웨어의 안정성을 높일 수 있다.
      • Increase software portability
      • ex) Applications can run on new hardware without modification

  • Isolation : GuestOS들 사이의 분리
    • Guest OS are isolated from each other
      • 하드웨어 위에서 하나의 OS만 동작하는 경우와 달리, 여러개의 GuestOS들이 분리되어 동작될 경우에 그 중 하나의 OS가 compromise(제대로 기능을 못하거나 외부에서 공격을 받은 상태)되더라도 다른 OS들은 살아남을 가능성이 크므로 안정성이 크다.
      • Increase system reliability
      • ex) Device driver failure does not affect other VMs

Q : malware가 device controller 쪽을 망가뜨릴 수도 있습니까? 만약 그렇다면 다른 guest os의 작동에도 영향을 줄수 있지 않을까요? A : 그렇다. 이런 경우를 대비해서 듀얼로 많이 하기도 한다. 듀얼은 두개의 OS가 하나의 하드웨어를 나눠가져서 동작하는 것이기 때문에 하나가 다운되어도 남은 하나는 영향을 받지 않는다.

Q : hypervisor를 적용시키게 되면 native와 native하지 않는 os가 모두 가동되있게 되는건가요? A : 그렇다.

Hypervisor

  • 특징
    • 가상화 컴퓨터 H/W 자원을 제공하기 위한 관리 계층
      • 게스트 OS와 H/W 사이에 위치함
        • 게스트 OS - hypervisor가 제공하는 가상화된 H/W 자원(virtual CPU - vCPU)을 이용하는 운영체제 -> 자신이 하드웨어를 실제로 사용하고 있다고 착각
      • 각 게스트 OS들은 각각 서로 다른 가상 머신(Virtual Machine)에서 수행되며 서로의 존재를 알지 못함 - isolation
        • H/W에 대한 접근은 hypervisor에게 할당 받은 자원에 대해서만 수행
      • Hypervisor는 각 게스트 OS 간의 CPU, 메모리 등 시스템 자원을 분배하는 등 최소한의 역할을 수행
        • hypervisor는 GuestOS가 필요한 만큼의 자원(vCPU, vMEM 등)을 유동적으로 제공한다.

Q : hypervisor는 커널의 기능을 모두 수행합니까? A : hypervisor는 OS의 커널이 가지는 기능 중 일부만 수행한다. hypervisor는 예를 들어 파일 시스템 I/O 같은 기능은 수행하지 않는다.

Q : virtual box를 설치하고 위에 Linux를 설치하는 과정에서 가상머신 메모리 설정을 1024, 2048 등으로 했었는데 이건 할당 할 수 있는 최대 메모리를 제한하는 것이었나요? A : 그렇다.

Hypervisor 장단점

hypervisor 기술이 발전한 2003년 이전에는 모놀리틱 커널과 마이크로커널의 성능 비교에 관한 논문이 학계의 주를 이뤘으나, 이후로부터는 hyperviosr 기술을 사용함으로써 얻을 수 있는 장점이 압도적이었으므로 논란이 정리되는 감이 없잖아 있었다.

  • 장점
    • 하나의 물리 컴퓨터에서 여러 종류의 게스트 OS 운용이 가능
      • 한 서버에서 다양한 서비스를 동시에 제공
    • 실제의 컴퓨터가 제공하는 것과 다른 형태의 명령어 집합 구조(Instruction Set Architecture)를 제공
      • 게스트 OS들이 서로 다른 명령어 집합을 사용하는 프로세스를 동시에 구동시킬 수 있다.
      • 다른 H/W 환경으로 컴파일된 게스트OS 및 응용프로그램도 실행 가능
  • 단점
    • H/W를 직접적으로 사용하는 다른 운영체제에 비해 성능이 떨어짐
      • 반가상화(Para-virtualization)로 성능저하 문제를 해결하려 함
        • GuestOS -> Hypervisor로 요청되는 Hypervisor Call에서 발생하는 오버헤드를 줄여 효율성을 크게 높인 것
        • 단 게스트 OS의 H/W 의존적인 코드(Hypervisor Call)에 대한 수정이 요구됨
          • 높은 기술적인 능력이 필요함
          • OS의 소스가 공개되지 않았다면 게스트 OS로 수정이 불가능

History of Hypervisor

  • 1960-1990
    • 초기 가상화 기술이 유용하지는 않지만 흥미로운 주제로써 연구되기 시작함
  • 1990-2000
    • VMware라는 회사에서 비록 낮은 성능이지만 가상화 소프트웨어를 개발함
  • 2000-2010
    • 반가상화가 개발
    • Intel에서 가상화를 통해 VT-X 하드웨어 서포트를 적용
      • 원래는 소프트웨어 측에서 모든 가상화를 책임졌으나, Intel과 같은 하드웨어 측에서 가상화를 지원하기 시작
    • 반가상화 & 하드웨어 서포트를 통한 성능 개선 -> 가상화 관련 기술, 산업 발달 ex) 클라우드
  • 2010-2020
  • I/O와 GPU의 가상화
  • ARM(임베디드 기기에서 사용되는 CPU의 한 종류)
  • 현재는 가상화를 쓰지 않는 기기를 찾기가 힘들 정도로 대부분의 기기에서 가상화 관련 기능이 빌트인되어있다.

경량화된 hypervisor

Xen이 상당한 센세이션을 불러일으켰음에도 불구하 여전히 문제가 있었던 점은 가상화 프로그램과 GuestOS 설치 과정의 까다로움이었다. OS에 대한 상당한 이해가 있어야 사용이 가능했다. KVM은 이 Xen의 문제를 해결하고자 했다.

  • KVM
    • 리눅스에 포함된 hypervisor
    • Xen의 paravirtualization을 없앰 -> Physical한 자원이 더 많이 사용되고 효율이 떨어짐
      • => Xen보다 정형화된 형태
    • 따라서 VT-x(Intel) 하드웨어를 이용한 성능 가속
    • 어렵지 않은 사용 방법

  • 컨테이너
    • smaller than (K)VM
      • OS/Kernel is shared
    • Lighter isolation
      • HostOS 위에 GuestOS 대신, Container engine을 올린다. 그리고 이 엔진 위에서 동작하는 컨테이너들이 HostOS의 커널을 사용한다.
      • Name spaces per container - 컨테이너에 네임스페이스를 줌으로써 경량화
        • 이전의 가상화와 다른 점은 네임스페이스 개념의 도입이다. 컨테이너들은 자기가 보는 네임스페이스가 정해져있다.
        • Limits what you see - 각 컨테이너가 볼 수 있는 범위가 네임스페이스 별로 분리되어 지정된다. 따라서 컨테이너 A는 컨테이너 B의 네임스페이스를 볼 수 없다. 하나의 커널을 컨테이너들이 공유하고 있지만 네임스페이스가 다르기 때문에 서로 분리되어 동작이 가능한 것이다.
      • Name space 다르면, 같은 이름 존재 가능 - 마치 한 컴퓨터 내의 파일 이름이 같아도 path가 다르면 존재할 수 있는 것처럼

More on Container

  • Container virtualize OS
    • Not hardware : Xen가 하드웨어를 가상화했다면 컨테이너는 OS를 가상화했다. 이를 통해서, 컨테이너 엔진과 호환이 되는 어떤 OS라면 뭐든 상관 없이 가상화가 가능하다.
    • Container engine: docker 등
    • 표준: OCI (Open Container Initiative) - 엔진의 인터페이스를 모아 표준화한 것
  • Container image (CI)
    • Include everything needed to run an application
      • program, runtime, system tools, system libraries and settings
    • CI will always run the same, regardless of the infrastructure
      • Write once, run anywhere : 어느 환경에서도 작동되기 때문에, migration 또한 가능하다.
      • Deployability : 코드를 여러 곳에 Deploy하기가 쉽다.
    • Comparison: Java
      • Java 또한 이 원리를 적용해서 Language 레벨에서 Write once, run any where을 실현하려고 했었지만, runtime 문제를 극복하지 못했다.
  • Weakness
    • OS 레벨에서의 isolation이 어려움
      • GuestOS 처럼 별도의 OS가 실행되는 것이 아니라, 하나의 커널 공간을 여러 개의 컨테이너가 공유하는 형태이므로

Q : KVM에서 Guest OS는 메모리는 할당받은 만큼만 사용하고 CPU는 다 같이 사용하나요? A : 그렇다. 다만 Hypervisor가 CPU 스케줄링을 하며, GuestOS는 이에 따라 할당된 CPU를 사용한다.

Q : 컨테이너 엔진은 컨테이너에게 버츄얼 머신을 제공하나요? A : 그렇다. 물론 KVM이나 Xen과 같은 수준으로 제공하는 것은 아니지만, CI를 모두 만들어 제공하므로 어느 OS 위에서나 동작할 수 있도록 HostOS를 가상화해주기 때문에 일종의 버츄얼머신을 제공한다고 할 수 있다.

Q : KVM과 컨테이너에서 자원 관리는 어디서 하나요? A : KVM에서는 HostOS와 더불어 각각의 GuestOS에서도 자원 관리를 하나, 컨테이너에서는 HostOS에서만 자원 관리가 이뤄진다.

Comments