Operating System Design and Implementation

6 minute read

운영 체제의 설계와 구현

 

운영 체제를 설계하고 구현하는 것은 완전히 해결이 가능한 문제가 아니다.

즉 이에는 유일한 해법이 존재하지 않는다.

다만 성공적이라고 증명된 접근법들이 존재한다.

 

먼저, 목적을 정의하고 이를 상세하게 만드는 것부터 시작한다.

이들은 하드웨어를 어떤 것을 쓸 것인지, 시스템의 유형은 어떻게 할 것인지 등이 해당한다.

시스템의 유형이란

  • 배치 시스템인지 time-sharing인지
  • 싱글 프로그래밍인지 멀티 프로그래밍인지
  • 범용 목적인지 특수 목적인지

등의 요소가 있다.

이는 성능에 가장 많은 영향을 미친다.

 

사용자의 목적과 시스템의 목적을 나누어서 생각하자.

 

사용자들은 운영 체제가 쓰기 편하고, 배우기 쉽고, 안정적이고

안전하고 빠르기를 원한다.

 

시스템들은 운영 체제가 설계, 구현, 유지하기 쉽고

또한 유연하며 안정적이고, 오류가 적고 효율적이길 원한다.

 

 

정책과 메커니즘을 분리하는 것은 매우 중요하다.

 

정책은 무엇이 행해질지를 말하는 것이고,

메커니즘은 그것이 어떻게 행해질지를 말하는 것이다.

정책은 장소나 시간에 따라서 변한다.

이때 유연성을 최대로 끌어올리기 위해선 정책과 메커니즘의 분리는 매우 중요한 원칙이다.

 

정책이 바뀔 때마다 메커니즘이 영향을 받아서 덩달아 바뀌어야 하는 시스템은

최악의 구현 방법이다.

가능하면 시스템은 정책에 민감하지 않아야 한다.

잘 설계하면 매개변수 정도만 바꿔서 정책을 즉각 반영할 수 있어야 한다.

구현

 

여러가지 방법이 있다.

이전의 운영 체제들은 어셈블리어로 구현이 됐다.

그러다가 Algol, PL/1 같은 시스템 프로그래밍 언어로 구현이 됐다.

요즘은 C, C++ 로 구현이 된다.

 

사실은 여러 언어로 구현이 된다.

가장 밑의 층에서는 하드웨어 접근에 용이하기 위해 어셈블리어로 구현한다.

메인은 C로 구현된다.

시스템 프로그램은 C, C++,

PERL, Python, 쉘 스크립트 같은 스크립트 언어로도 구현된다.

 

더 고수준의 언어는 다른 하드웨어로 이식하기에 쉽지만 느리다.

 

에뮬레이션으로 운영 체제를 여러 종류의 하드웨어에서 돌릴 수 있다.

이는 느리지만 개발 시에는 개발의 편의상을 위해 사용된다.

 

운영 체제 구조

 

범용 운영 체제는 매우 넓은 범위의 프로그램이다.

운영 체제 같이 큰 프로그램은 나중에 변경하기 쉽도록 구조를 잘 만들어야 한다.

운영 체제의 구조를 설계하는 것에는 여러 방법이 있다.

 

간단한 구조 : MS-DOS

 

 

  • 초창기 PC에서 사용됐다.

  • 최소한의 공간에서 최대의 기능을 제공하기 위해 설계됐다.

  • 모듈화 되어 나누어지지 않았다.

  • MS-DOS 도 나름 구조를 가지고 있으나

    인터페이스와 기능에서의 단계가 잘 나눠지지 않았다.

  • 커널의 일부 기능은 resident program이 담당한다.

    이들은 RAM에 상주하며 커널의 기능을 수행한다.

    MS-DOS는 매우 단순하여,

    경우에 따라 응용 프로그램이 ROM BIOS에 직접 접근도 가능하다.

위의 resident system program과 MS-DOS device drivers 가 커널에 해당한다.

이는 맨 밑의 ROM BIOS 라는, 기본적인 입출력 접근 프로그램에 의존한다.

응용 프로그램이 커널에게 입출력을 요구하면 커널이 이를 ROM BIOS에게 전달하는 식으로 작동한다.

위에서 설명했든 맨 오른쪽 화살표를 보면 응용 프로그램도 ROM BIOS로 직접 이어질 수 있음을 확인할 수 있다.

 

결론적으로 MS-DOS는 구조 측면에서 보면 매우 단순하고

가지고 있는 기능들이 내부적으로 잘 분리되어 있지 않고

외부에 제공하는 인터페이스도 정의되어 있지 않다.

 

 

UNIX

 

 

초창기의 유닉스 운영 체제의 구조도이다.

이는 각종 시스템 프로그램과 커널로 이루어져 있다.

 

유닉스는 하드웨어의 기능성에 한정되어 작동하며

원래 유닉스 운영 체제는 한정된 구조를 가졌다.

유닉스 운영 체제는 두 부분으로 나뉜다.

  • 시스템 프로그램

  • 커널 (다소 제한적인 커널이다)

    • 시스템 콜 인터페이스 밑부터

      물리적인 하드웨어 위까지의 모든 것을 구성한다.

    • 파일 시스템, CPU 스케쥴링, 메모리 관리,

      하나의 계층에서 여러가지 운영 체제 기능들을 제공한다.

 

여기서 하나의 계층이란, 커널 부분이 수평적으로 계층 없이 이루어져 있음을 의미한다.

UNIX 운영 체제의 구조는 전체적으로 보면

사용자 - 시스템 프로그램 - 커널 - 하드웨어의 계층적 구조이나

커널만 놓고 보면 그렇지 않다.

CPU 스케쥴링이나 메모리 관리 같은 기능이 커널 안에 다 담겨져 있을 뿐

이들 사이의 계층적 구조를 가지고 있지 않다.

이를 Monolithic 한 구조라고 한다.

이는 성능상의 장점이 있긴 하나 워낙 기능이 많아서 구현과 유지 보수가 어렵다.

 

 

계층적인 접근

 

 

시스템을 모듈화하는 방법 중 하나는 전체 시스템을 계층적으로 구현하는 것이다.

위의 UNIX는 언뜻 보면 계층적 구조이나 커널은 계층적이지 않아서

진정한 의미의 계층적 구조라고 하면 곤란하다.

본격적인 계층 구조라면 커널도 계층적으로 이루어져야 한다.

 

계층적인 구조에서 운영 체제는 많은 수의 계층(layer 혹은 level)로 나눠진다.

각각은 하층의 위에서 구현이 된다.

그림에서와 같이 layer 1은 그의 하층인 layer 0 위에서 구현이 되어 있다.

바닥 계층 (layer 0)은 하드웨어이고, 가장 높은 계층 (layer N)은 사용자 인터페이스이다.

커널은 layer 1부터 layer N 아래의 사이에 해당한다.

 

모듈성으로 계층들은 그 계층들의

자기보다 더 아래층의 기능과 서비스만 사용할 수 있다.

 

커널이 여러개의 계층으로 나뉘는 경우 각 계층은 데이터와,

이를 조작하는 연산으로 구성된 추상화된 개체라고 할 수 있다.

전형적으로 한 계층은 자신의 자료구조와 코드, 그리고 아래 계층의 함수 호출로 이어진다.

계층적인 접근 방식의 큰 장점은 구현과 디버깅이 간단하다는 점이다.

각 계층은 자신의 하위 계층만 쓸 수 있기 때문에 디버깅, 검증이 간단하다.

 

계층적 구조가 디버깅이 간편한 이유는 다음과 같다.

layer 2는 layer 1만 건드릴 수 있다.

또한 상위 계층은 하위 계층이 어떻게 돌아가는지(자료구조, 함수 등)는 전혀 관심이 없다.

무슨 함수가 있고, 뭘 반환하는지에만 관심이 있을 뿐이다.

때문에 layer 2는 layer 1이 완벽하다는 가정하에 구현이 된다.

한 계층에서 오류가 발생하면, 이전 계층이 완벽하다고 가정하기 때문에

오류는 그 안에 있다고 보장할 수 있는 것이다.

 

단 이는 설계 시에 여러 층을 적절하게 배분하는 것이 어렵다는 단점이 있다.

또한 각 층은 자기 하위의 층만 건드릴 수 있기 때문에 이 설계가 신중해야 하고

하나의 동작이 여러 계층을 거치게 될 수 있기 때문에 효율성이 떨어질 수도 있다.

 

 

마이크로커널 시스템 구조

 

 

UNIX와 같은 monolithic 한 커널이 점차 커지고 복잡하게 되자

1980년 마이크로커널에 기반한 Mach라는 운영 체제가 개발이 되었다.

마이크로커널은 UNIX의 monolithic 한 커널 구조 중

일부를 커널에서 떼어내어 사용자 수준으로 구현하고,

대신 커널 안에는 아주 기본적인 기능만 남겨놓은 작은 커널을 의미한다.

마이크로커널에서 어떤 것이 사용자 프로그램으로 올라가고 어느 것이 남아있는지는 정해지지 않았다.

Mach 의 예는 프로세스, 메모리, 통신만 남겨 놓았다.

Mac 운영 체제의 X 커널 (Darwin)이 부분적으로 Mach 를 따랐다.

 

사용자 모듈 사이에 통신 기능이 메시지 전달을 위해 자리잡고 있다.

응용 프로그램과 파일 시스템, 파일 시스템과 장치 드라이버가

직접 통하지 않고 커널을 통한 메시지 전달로 통하게 된다.

 

이 마이크로커널 구조의 장점은

  • 커널을 바꿀 필요가 없음. 바꿔도 커널 자체가 작아서 괜찮다.

  • 마이크로커널을 확장하기에 쉽다.

  • 운영 체제를 새 구조에 이식하기 쉽다.

  • 하드웨어 이식이 쉽다.

  • 커널 모드에서 돌아가는 코드가 적어서 안정성 있다.

  • 운영 체제의 기능 대부분이 커널이 아니라

    사용자 프로그램에서 실행되어서 안전하다.

 

monolithic 한 커널에서보다 성능은 떨어진다.

왜냐하면 수 차례의 메시지 전달이 이루어지고 시스템 콜이 빈번하게 일어나기 때문이다.

monolithic 한 구조에서는 커널 공간에서 커널끼리 통신할 수 있는데,

마이크로커널에서는 몇 개가 사용자 공간(user space)으로 올라갔기 때문에

그런 기능들이랑 통하려면 사용자 공간이랑도 메시지를 주고 받아야 해서

성능상 오버헤드(추가 시간)가 발생한다.

 

 

모듈

 

 

정식 이름으로는 loaderble kernel modules이라고 한다.

이는 가장 현대적인 운영 체제 구현 방법이다.

 

위 그림에서 파란 원은 커널 모듈들이다.

커널 모듈은 커널의 핵심적인 기능 이외에 동적으로 추가될 수 있는 서비스이다.

부팅 시점부터 연결되진 않고, 필요하면 연결이 된다. 탈부착할 수 있는 것이다.

커널을 다 빌드할 필요도 없고, 커널을 작은 규모로 유지가 가능하여 편리하다.

 

모듈화된 구조는 객체 지향적인 접근 방식을 이용한다.

각 핵심 요소는 분리되어있다.

각각은 인터페이스를 통해 서로 대화할 수 있다.

커널에서 필요하면 로드가 된다.

 

전체적으로 보면 계층 구조와 비슷한데 더 유연하다.

리눅스, 솔라리스 등이 이 구조로 되어있다.

 

 

하이브리드 시스템

 

 

현대의 운영 체제는 사실 하나의 모델만을 따르지 않는다.

성능, 보안, 사용상의 필요를 위해 하이브리드한 구조를 사용한다.

 

리눅스와 솔라리스 커널은 monolithic 과 동적인 적재와 기능성을 위한 모듈화도 가능하다.

Windows는 대부분 monothic 하고, 마이크로커널도 따른다.

애플의 Mac 운영 체제 X 는 하이브리드, 계층적인 Aqua UI와 Cocoa 프로그래밍 환경을 가지고 있다.

아래는 Mach의 마이크로커널과 BSD 유닉스, 입출력 키트,

커널 확장으로도 불리는 동적으로 로드 가능한 모듈 (dynamically loadable modules) 로 이루어져 있다.

 

위 그림은 운영 체제 X의 구조를 나타낸 것이다.

위에서 설명한 대로, 맨 위에 Aqua UI가 있고

밑의 커널 환경에서 BSD 환경이 있어 사용자가 이 MacOS를 마치 BSD 환경처럼 사용 가능하며

그 외부는 Mach의 마이크로커널을 사용하며,

그 밑에선 커널 모듈을 동적으로 추가해 확장할 수 있다.

 

 

iOS

 

 

iPhone, iPad에서 돌아가는 애플의 모바일 운영 체제이다.

이들은 Mac OS X 상에서 구현되어 모바일 장치에 특화된 기능을 제공한다.

하지만 Mac OS 의 기능을 직접 실행할 수는 없다.

 

Cocoa Touch 는 앱 개발을 위한 Objective-C API이다.

모바일 장치 상에서 개발되는 응용 프로그램들을 위한 여러 프레임워크를 제공한다.

Media Services 계층은 그래픽, 오디오, 비디오를 위한 계층이다.

Core Services 는 클라우드 컴퓨팅, 데이터베이스를 제공한다.

 

 

Android

 

 

  • Open Handset Alliance 에서 개발되었다.

  • 리눅스 커널에 기반하나, 수정되었다.

    • 프로세스, 메모리, 디바이스 드라이버 관리를 제공한다.

    • 여기에 전력 관리가 추가되었다.

  • 런타임 환경에는 핵심 라이브러리와 Dalvik 가상 머신이 있다.

    • 자바와 안드로이드 API로 개발된다.

    • 자바 클래스 파일들은 자바 바이트코드로 컴파일 되고 실행 가능한 상태로 번역되어

      Dalvik 가상 머신에서 돌아간다.

  • 라이브러리에는

    • 웹 브라우저(웹킷)

    • 데이터베이스(SQLite)

    • 멀티미디어

    • 표준 C library

      그 밖의 작은 라이브러리들을 위한 프레임워크들이 있다.