[운영체제] 운영체제의 설계 구조(Operating System Design and Structure)

참고도서: Operating System Concepts (9/E) Abraham Silberschatz, Peter B. Galvin, Greg Gagne

Operating System Design and Implementation

Design Goals

운영체제를 설계할 때, 다른 고려요소들이 많지만 가장 근본적으로 고려해야하는 것이 사용자 목적과, 시스템 목적이다.

사용자들은 어떤 시스템이 가지고 있어야할 특징들을 요구한다. 시스템은 사용하기에 편해야하고, 안전하고 빨라야한다. 그리고 이 운영체제를 설계하는 사람들의 입장에서는 설계, 구현, 유지/보수가 쉬워야 한다.

Mechanisms and Policies

Mechanism은 어떻게 할 것인가에 대한 내용이고 Policy는 무엇을 할 것인가를 결정하는 내용이다. 이 두 영역을 분명하게 분리하는 것이 정말 중요하다. 특히 정책에 대한 결정은 컴퓨터의 리소스를 할당하는 데 있어서 굉장히 중요한 문제이다. 어떤 리소스를 할당하기 위해서 시스템은 정책을 따르게 될 것이고 이 때문에 정책을 잘 결정하는 것은 중요하다.

Implementation

초기의 운영체제는 어셈블리어로 작성되었지만 지금은 C나 C++로 작성되고 있다. 이렇게 고급 언어로 발전하게 된 이유는 여러가지가 있다. 쉽게 코드를 작성할 수 있고, 더 이해하기 쉽기 때문에 디버깅도 쉬워진다. 그리고 결정적으로 다른 운영체제에 이식하는 것이 굉장히 편해진다.

반면에 단점도 존재한다. 어셈블리어에 비해 속도가 느리고, 저장공간이 많이 요구된다. 그리고 어셈블리어에 비해 세밀한 작업을 하는 데에 불리하다. 하지만 최근에 들어 하드웨어가 엄청난 발전을 이루었고, 저장장치는 운영체제 설계에 있어 큰 이슈는 아니게 되었다. 그것보다 더 중요한 것은 운영체제를 구성하는 자료구조와 알고리즘의 질이 되었다.

Operating System Structure

Monolithic Structure

가장 단순한 운영체제의 구조는 구조가 없는 것이다. 커널의 기능을 모두 단일한 바이너리 파일에 넣는 방식이다. 그리고 이 방식은 많은 운영체제에서 사용되는 일반적인 구조이다. UNIX의 전통적인 구조가 가장 좋은 예시인데, UNIX는 system call interface 와 물리적인 하드웨어 사이에 모든 커널의 기능들이 들어가있다. 같은 맥락에서 생각해보면 운영체제가 하는 일이 굉장히 많은데 그 모든 기능들이 하나의 파일안에 집약적으로 들어있다는 것을 뜻한다. 리눅스를 비롯한 많은 운영체제에서 이 구조를 사용한다.

단점:

  1. 단일한 파일에 모든 기능이 들어가기 때문에 구현과 확장이 어렵다.

장점:

  1. 스템 콜에 있어서 오버헤드가 적게 발생하고 커널 내에서 통신속도가 빠르다.

Layered Approach

계층으로 운영체제의 구조를 나누는 방법도 있다. 운영체제의 여러 층으로 나누게 되는데 최하위 층인 0 층은 하드웨어, 최상위 층은 계층에 개수에 따라 N층이라고 한다. 이런 방식은 각 계층이 자신의 하위층들에 의해 제공된 연산만으로 구현된다.

단점:

  1. 사용자 프로그램이 원하는 서비스를 얻기위해 각 계층을 통과해야하는 오버헤드가 발생한다.

장점:

  1. 구현과 디버깅이 간단하다. 한 층은 자신의 하위 층들이 가진 서비스와 연산만을 이용할 수 있기 때문에 어떤 층에 대한 디버깅이 마치면, 그 상위층에 대한 디버깅은 해당 층으로만 국한할 수 있다.
  2. 각 층에 대한 정보가 보호된다. 각 층은 자신과 하위층들의 연산만을 이용해 구현되기 때문에 자신의 하위 층이 어떻게 구현되었는지 알 필요없이 그냥 그 연산을 가져다 쓰기만 하면된다.

Microkernels

앞서 언급했던 것 처럼 초기 UNIX는 Monolithic 구조로 이루어져 있었다. 그런데 UNIX가 점점 확장함에 따라 단일한 커널에 모든 기능을 담고 관릴하는게 어려워졌다. 이 문제를 해결하기 위해서 커널을 모듈화 하는 방식은 microkernel 방식이 개발되었다. microkernel 방식의 구조는 커널 내의 불필요한 기능들을 모두 user-level 프로그램으로 분리하는 것으로 구현된다. 결과적으로는 커널의 크기가 작아진다.

microkernel의 중요한 기능은 client 프로그램과 user space에서 실행되고 있는 다양한 서비스들 간의 통신을 지원하는 일이다. 이 통신은 massage passing 방식으로 이루어져 있다. client program은 직접적으로 시스템 서비스에 접근하지 않고 server를 통해서만 접근하게 된다.

단점:

  1. 서비스를 얻기위해 메세지를 보내고 프로세스를 전환하는 과정에서 오버헤드가 발생한다.

장점:

  1. 운영체제의 확장이 쉽다. 새로운 서비스는 사용자 공간에 추가하기만 하면 되기 때문에 기존 커널을 변경하지 않고 새로운 기능을 추가할 수 있다.
  2. 한 서비스가 잘못되더라도 커널 전체에 문제가 발생하지 않는다.

Modules

운영체제를 설계하는데 가장 좋은 방법은 Loadble Kernel Module(LKM)을 사용하는 것이다. 이 방식은 현대 UNIX 기반의 운영체제들이 대부분 사용하고 있는 방식이기도 하다. 이 구조에서 제일 중요한 것은 커널에는 핵심적인 서비스들만 넣어두고 다른 서비스들은 커널이 실행되는 동안 동적으로 동작하도록 만드는 것이다. 커널에 직접적으로 어떤 기능을 추가하게 되면 새로 커널을 컴파일해야하는 문제가 발생하게 되는데 이 문제를 쉽게 해결할 수 있다. 결과적으로 이 구조는 커널이 여러 부품처럼 정의되고 연결되어 있다는 점에서 layered approach와 비슷하지만 계층구조의 오버헤드가 없고, 각 세부구조들이 서로 통신하면서 호출한다는 점에서 microkernel 과 비슷하지만 message passing 을 사용하지 않기 때문에 효과적이다.

Hybrid System

앞서 이야기 했던 여러 구조와 접근들을 모두 결합하여 성능이나 보안 이슈들을 해결하려는 노력 끝에 hybrid system이 제안되었다. 예를 들어 Linux와 Windows 모두 성능을 위해 monolithic 구조를 사용하지만 Linux는 module을 사용하여 새로운 기능을 동적으로 커널에 추가할 수 있도록 하고, Windows는 커널을 여러개로 쪼개어 운영하는 microkernel 방식을 더하여 사용하고 있다.

How Mac OS X and IOS OS Work?

Structure

Apple의 주요 운영체제인 macOS 왕 IOS 는 여러개의 층으로 표현할 수 있다.

  1. user experience 에서는 사용자가 시스템과 상호작용할 수 있는 인터페이스를 제공한다. macOS에서는 트랙패드를 사용하기 위한 Aqua를 제공하고, IOS에서는 터치를 통한 조작을 지원하기 위해 springboard 를 제공한다.
  2. application frameworks 에서는 Cocoa 및 Cocoa Touch 프레임워크를 포함하고 object-c 와 swift에 대한 API가 제공 된다.
  3. core frameworks 에서는 Quick Time, OpenGL 같은 그래픽, 미디어 프레임워크 들이 지원된다.
  4. Darwin은 Mach 라는 micro kernel과 BSD라는 UNIX kernel로 이루어져 있는데 더 자세한 내용은 뒤 부분에서 더 자세히 설명하겠다.

응용프로램들은 다른 모든 층에 직접적으로 상호 작용할 수 있다.

Darwin

Darwin은 hybrid 구조를 사용하는 kernel enviroment 이다. Darwin은 계층으로 이루어져있는데, 이 계층을 구성하는 것이 Mach 와 BSD이다.

대부분의 운영체제는 하나의 system call interface 를 제공하는데, Darwin은 Trap이라고 부르는 Mach system call과 BSD system call을 제공한다. Mach 는 메모리 관리, CPU scheduling, 등 기본적인 운영체제의 기능을 담당하게 된다. Mach가 제공하는 기능들은 커널 추상화를 통해서 사용된다. 응용프로그램의 프로세스는 BSD의 POSIX systemcall 을 통해서 생성된다. macOS는 커널 환경에 장치 드라이버 및 LKM 개발을 위한 IOkit 제공하기도 한다.

기본적으로 microkernel에는 message passing으로 인한 메세지 복사와 프로세스 전환에 오버헤드가 발생하는게 문제가 있었다. 이 문제를 해결하기 위해서 Darwin은 내부의 모든 구성요소들을 단일한 주소공간에 넣어둔다. 따라서 Mach내의 message passing은 불필요해지고, 메모리 주소를 통해서 직접적으로 통신하는 것이 가능해졌다.

How Android OS Works?

Android는 오픈소스로 진행된 프로젝트이기에 짧은 시간동안 엄청난 발전을 이루었다. Android 는 기본적으로 Java 언어를 기반으로 하지만 Java의 API를 따르지 않고 독자적으로 Android API를 만들어 사용하고 있다. Android 를 위해 만들어지는 모든 프로그램은 Android Run Time 이라고 부리는 ART에서 실행될 수 있는 형태로 컴파일 되는데, 이는 모바일에 최적화 되어있는 가상머신이다.

Android 개발자는 Java Native Interface 를 사용하는 Java 프로그램을 작성하게 된다. 그리고 웹브라우저를 위한 webkit, 데이터베이스를 위한 SQLite, 그리고 네트워크 소켓을 위한 SSL 프레임워크가 라이브러리로 지원된다.

리눅스 시스템에서는 표준 C 라이브러리로 GNU C를 사용하는데 반해 Android는 구글에서 개발한 Bionic 표준 라이브러리를 사용하고 있다. 그리고 이 모든 구조의 제일 아래에는 Linux 커널이 있어 기본적인 운영체제의 기능을 제공하고 있다. 물론 이 Linux 커널도 Android 시스템에 맞게 수정되어 있다.


Written by@전여훈 (Click Me!)
고민이 담긴 코드를 만들자, 고민하기 위해 공부하자.