운영체제 02

‘Operating System Concepts 8th’를 정리한 글이다.

2.1 운영체제 서비스

운영체제는 프로그램 실행 환경을 제공한다. 운영체제 서비스는 프로그래머가 보다 쉽게 프로그래밍 할 수 있도록 프로그래머에게 편리함을 제공한다.

image
운영체제 서비스 개관
  • 사용자 인터페이스 : 명령어 라인 인터페이스로서 cmd 창 같은 것, 명령어와 명령어를 제어하는 디렉티브(directive)가 파일 형태로 입력되어 파일이 실행되는 배치 인터페이스(batch interface), 그래피컬 사용자 인터페이스(GUI). 이렇게 3가지 종류가 있다.
  • 프로그램 실행 : 시스템은 프로그램을 메모리에 적재해 실행하며 프로그램은 정상이든 비정상이든(에러를 표시하며) 실행을 끝낼 수 있어야 한다.
  • 입출력 연산(I/O operation) : 실행 중인 프로그램은 입출력을 요구할 수 있다. 효율과 보호를 위해 사용자들은 I/O를 직접 제어할 수 없다. 그렇기에 운영체제가 입출력 실행의 수단을 제공한다.
  • 파일 시스템 조작 : 프로그램은 파일을 읽고 쓸 필요가 있다. 운영체제는 프로그램이 요구하는 다양한 특정 특성과 성능 특성을 제공하기 위해 다양한 파일 시스템을 제공한다.
  • 통신 : 통신은 두 가지로 나눌 수 있다. 동일한 컴퓨터에서 실행되는 프로세스들 사이에서 일어나는 통신, 컴퓨터 네트워크에 의해 함께 묶여 있는 다른 컴퓨터 시스템 상에서 실행하는 프로세스들 간의 통신. 공유 메모리, 메시지 전달 기법에 의해 구현될 수 있으며 후자의 경우엔 정보 패킷이 이동한다.
  • 오류 탐지 : 운영체제는 모든 가능한 오류를 의식하고 있어야 한다.
  • 자원 할당 : 다수의 사용자나 다수의 작업들이 동시에 실행될 때, 그들 각각에 자원을 할당한다. 운영체제는 CPU 등 자원을 최대한 효율적으로 이용하기 위해 스케줄링을 실행한다.
  • 회계 : 사용자가 어떤 종류의 컴퓨터 자원을 얼마나 사용하는지 관리하고자 한다.
  • 보호와 보안 : 서로 다른 여러 프로세스가 동시에 실행될 때 한 프로세스가 다른 프로세스나 운영체제 자체를 방해해서는 안 된다. 보호는 시스템 자원에 대한 모든 접근이 통제되도록 보장하는 것이 포함된다.

2.2 사용자 운영체제 인터페이스

여러가지 인터페이스 중 명령 해석기와 GUI. 두 가지 기본적인 방법에 대해 논의한다.

2.2.1 명령 해석기

명령어 해석기의 중요한 기능은 사용자가 지정한 명령을 가져와서 그것을 실행하는 것이다. 이 수준에서 제공된 많은 명령들은 파일을 조작한다. 생성, 삭제, 리스트, 프린트, 복사, 실행 등을 한다.

2.2.2 그래피컬 사용자 인터페이스

이 방식은 직접 명령어를 입력하는 것이 아니라 마우스를 기반으로 하는 윈도우 메뉴 시스템을 사용한다.

2.3 시스템 호출(System Calls)

시스템 호출은 운영체제가 제공하는 서비스에 대한 인터페이스를 제공한다. 특정 저수준 작업(예를 들면, 하드웨어를 직접 접근)은 어셈블리 명령을 사용하더라도 C나 C++ 언어로 작성된 루틴 형태로 서비스를 제공한다. 예를 들어 원래 파일에서 다른 파일로 저장할 경우 수많은 시스템 호출을 날리게 된다.

image
시스템 호출이 사용되는 예

대부분의 사용자는 이런 상세한 사항을 결코 알지 못 한다.

막후에서 API를 구성하는 함수들은 통상 응용 프로그래머를 대신하여 실제 시스템 호출을 호출한다. 예를 들어 Win32 함수 CreateProcess()(프로세스 생성)은 실제로 Windows 커널의 NTCreatePorecess() 시스템 호출을 부른다. 그렇다면 왜 응용 프로그래머는 실제 시스템 호출을 부르는 것보다 API에 따라 프로그래밍하는 것을 선호할까?

API에 따라 프로그래밍 하는 한 가지 이점은 프로그램의 호환성과 관련 있다. API에 따라 프로그램을 설계한다면 같은 API를 지원하는 어느 시스템에서건 컴파일 되고 실행된다는 것을 기대할 수 있다.

호출자는 시스템 호출이 어떻게 구현되고 실행 중 무슨 작업을 하는지 아무 것도 알 필요가 없다. 단지 API를 준수하고 시스템 호출의 결과로 운영체제가 무엇을 해줄 것인지만 이해하면 된다. 밑처럼 시스템 호출은 알아서 커널 모드로 변환하여 작업을 실행한다.

image
Open() 시스템 호출을 호출한 사용자 응용의 처리

2.4 시스템 호출의 유형

시스템 호출은 다섯 가지의 중요한 범주 프로세스 제어, 파일 조작, 장치 조작, 정보 유지 보수와 통신과 보호 등으로 묶을 수 있다.

2.4.1 프로세스 제어(Process Control)

실행 중인 프로그램은 정상적 또는 비정상적으로 끝낼 수 있어야 한다. 만약 현재 실행 중인 프로그램을 비정상적으로 중지하기 위해 시스템 호출이 행해지거나 프로그램에 문제가 발생해 오류 트랩이 유발되면 때때로 메모리 덤프가 행해지고 오류 메시지가 생성된다.

한 프로그램을 실행하고 있는 프로세스나 잡이 다른 프로그램을 적재(load)하고 실행(execute)하기를 원할 수 있다. 이 때 적재된 프로그램이 종료되었을 때 어디로 제어를 되돌려주는가 하는 질문이 나올 수 있다. 기존 프로그램이 유실될지, 보관될지, 새로운 프로그램과 병행해 실행을 계속하도록 허용할 것인지 하는 문제가 있다.

만약 새로운 프로그램이 종료되었을 때 제어가 기존 프로그램으로 되돌아간다면, 반드시 기존 프로그램의 메모리를 보관해야한다. 이러면 한 프로그램이 다른 프로그램을 호출하는 기법을 만든 셈이 된다.

두 프로그램이 병행하여 실행되는 경우라면 다중 프로그래밍이 될 새로운 잡이나 프로세스를 생성한 것이 된다.

만약 새로운 잡이나 프로세스 혹은 잡들이나 프로세스들의 집합을 생성한다면 이들의 실행을 제어할 수 있어야 한다. 이러한 제어는 잡의 우선순위, 최대 허용 실행시간 등을 포함하여 잡/프로세스의 속성들을 결정하고 재설정 할 수 있어야 한다.

프로세스와 잡 제어는 너무 많은 측면과 다양성이 있기에 이러한 개념을 명확히 하기 위해 단일 태스킹 시스템과 다중 태스킹 시스템의 두 예를 사용한다.

MS-DOS 운영체제는 단일 태스킹이기에 하나의 프로그램을 실행하기 위해 간단한 방법을 사용하며 새로운 프로세스를 생성하지 않는다.

FreeBSD는 다중 태스킹 시스템이다. 명령 해석기는 다른 프로그램이 실행되는 동안 실행을 계속 할 수 있으며 새로운 프로세스를 시작할 때 fork() 시스템 호출을 실행한다.

2.4.2 파일 관리

사용자는 파일을 생성, 삭제할 수 있어야 한다. 파일 이름이나 파일 속성의 일부를 요구하거나 이것을 열고 읽고 쓰고 위치 변경 등의 일을 할 수 있어야 한다. 이런 작업들은 운영체제가 시스템 호출을 제공함으로서 이루어진다.

2.4.3 장치 관리

프로세스는 작업을 계속 실행하기 위해 추가 자원을 필요로 할 수 있다. 주 기억장치, 디스크 드라이브, 파일 접근 등이 그런 예이다.

다수의 사용자가 동시에 사용하는 시스템은 독점적인 장치 사용을 보장받기 위해 우선 그 장치를 요청(request)해야만 한다. 그 장치의 사용이 끝나면 반드시 방출(release)해야 한다. 이 때 예상되는 위험은 잠재적 경쟁과 교착상태이다.

2.4.4 정보의 유지

많은 시스템 호출은 단순히 사용자 프로그램과 운영체제간의 정보 전달을 위해 존재한다. 더욱이 운영체제는 현재 운영되고 있는 모든 프로세스들에 관한 정보를 가지고 있으며, 이러한 정보에 접근하기 위한 시스템 호출들이 있다.

2.4.5 통신

통신 모델에는 메시지 전달과 공유 메모리의 두 가지 일반적인 모델이 있다.

메시지 전달 모델은 두 프로세스 사이에 직접 교환되거나 우편함을 통하여 간접적으로 교환될 수 있다. 통신이 이루어지기 전에 연결이 반드시 열려야 한다. 각 프로세스는 프로세스 이름(PID)를 가지고 있으며 이 이름은 운영체제에 의해 동등한 식별자로 변환된다. 서로 구분이 된 프로세스들은 연결 후에 메시지를 주고 받는다.

공유 메모리 모델에서 프로세스는 다른 프로세스가 소유한 메모리 영역을 생성하고 접근하기 위해 shared memory create와 shared memory attach 시스템 호출을 사용한다. 정상적으로 운영체제는 한 프로세스가 다른 프로세스의 메모리를 접근하는 것을 막으려고 한다. 공유 메모리는 두 개 이상의 프로세스가 이러한 제한을 제거하는 데 동의할 것이 필요하다. 그런 후 이 프로세스들은 이런 공유 영역에서 데이터를 읽고 씀으로써 정보를 교환한다.

데이터 형식은 운영체제의 제어하에 있는 것이 아니라 이들 프로세스들에 의해 결정되며 프로세스들은 동일한 위치에 동시에 쓰지 않도록 보장할 책임을 지닌다.

메시지 전달은 소량의 데이터를 교환할 때 유용하다. 공유 메모리는 한 컴퓨터 안에서 메모리 전송 속도로 실행할 수 있기 때문에 최대 속도와 편리한 통신을 허용하지만 보호와 동기화 부분에서 여러 문제점을 가지고 있다.

2.4.6 보호

보호는 컴퓨터 시스템이 제공하는 자원에 대한 접근을 제어하기 위한 기법을 지원한다.

2.5 시스템 프로그래밍

논리적인 컴퓨터 계층 구조는 하드웨어 -> 운영체제 -> 시스템 프로그램 -> 응용 프로그램 순으로 계층이 나눠져있다.

시스템 프로그램은 시스템 유틸리티로도 알려진 프로그램 개발과 실행을 위해 보다 편리한 환경을 제공한다. 이들은 다음 몇 가지 범주로 분류할 수 있다.

  • 파일 관리 : 이들 프로그램은 파일과 디렉터리를 생성, 삭제, 복사, 개명, 인쇄, 덤프, 리스트를 하며 일반적인 조작을 한다.
  • 상태 정보 : 프로그램은 시스템에게 날짜, 시간, 사용 가능한 메모리 등 상태 정보를 묻는다. 몇몇 시스템은 환경설정 정보를 저장하고 검색할 수 있는 등록(registry) 기능을 지원하기도 한다.
  • 파일 변경 : 디스크나 다른 저장장치에 저장된 파일의 내용을 생성하고 변경하기 위해 다수의 문장 편집기가 사용 가능하다.
  • 프로그래밍 언어 지원 : C, C++, Java 등에 대한 컴파일러, 어셈블러, 인터프리터가 제공된다.
  • 프로그램 적재와 실행 : 프로그램이 어셈블 되거나 컴파일된 후 그것이 실행되려면 메모리에 적재되어야 한다.
  • 통신 : 프로세스, 사용자, 다른 컴퓨터 시스템들 사이에 가상 접속을 이루기 위한 기법을 제공한다.

대부분의 사용자가 보는 운영체제의 관점은 실제 시스템 호출에 의해서라기보다 시스템 프로그램과 응용에 의해서 정의된다.

2.6 운영체제 설계 및 구현

2.6.1 설계 목표

시스템을 설계하는 데 첫째 문제는 시스템의 목표와 명세를 정의하는 일이다. 시스템 설계는 하드웨어와 시스템 타입(일괄처리, 시분할, 단일 사용자, 다중 사용자, 분산, 실시간 혹은, 범용)의 선택에 의해 영향을 받을 것이다.

내장형 시스템을 위한 실시간 운영체제인 VxWorks를 위한 요구 조건은 IMB 대형 컴퓨터를 위한 대규모 다중 사용자, 다중 접근 운영체제인 MVS를 위한 요구 조건과는 크게 달랐다.

2.6.2 메커니즘과 정책

한 가지 중요한 원칙은 메커니즘으로부터 정책을 분리하는 것이다. 메커니즘은 어떤 일을 어떻게 할 것인가를 결정하는 것이고, 정책은 무엇을 할 것인가를 결정하는 것이다. 예를 들면 타이머 구조는 CPU 보호를 보장하기 위한 메커니즘이지만, 특정 사용자를 위해 타이머를 얼마나 오랫동안 설정할 지를 결정하는 것은 정책적 결정이다.

정책은 장소가 바뀌거나 시간이 흐름에 따라 변경될 수 있다. 최악의 경우, 정책의 각 변경이 저변에 깔려 있는 메커니즘의 변경을 요구하게 된다. 정책의 변경에 민감하지 않은 일반적인 메커닞므이 보다 바람직하다.

정책 결정은 모든 자원 할당 문제에 있어 중요하다. 자원의 할당 여부를 결정할 필요가 있을 때마다 정책을 결정해야 한다. 질문이 무엇(what)이 아니라 어떻게(how)일 때 결정되어야 하는 것은 메커니즘이다.

2.6.3 구현

예전에 운영체제는 어셈블리어로 작성되었지만 현재 거의 대부분 운영체제는 C나 C++로 작성된다.

2.7 운영체제 구조

운영체제 같이 복잡한 시스템이 적절하게 동작하고 쉽게 변경될 수 있으려면 신중히 제작되어야 한다. 일반적인 접근 방법은 한 개의 모놀리식 시스템보다는 태스크를 작은 구성요소로 분할하는 것이다.

2.7.1 간단한 구조

MS-DOS가 대표적 예이다. 응용 프로그램은 기본 입출력 루틴을 통해 디스플레이와 디스크 드라이브에 직접 쓰기가 가능하다. 이런 자유는 MS-DOS를 오류가 있는 프로그램으로부터 취약하게 만들었다. 따라서 사용자 프로그램이 고장나면 시스템 전체가 고장나게 된다.

2.7.2 계층적 접근

적절한 하드웨어 지원이 있을 경우 운영체제는 MS-DOS보다 작고 보다 적절한 조각으로 분할될 수 있다.

계층적 접근 방식은 운영체제가 여러 개의 층으로 나누어진다. 이 계층적 접근 방식의 주된 장점은 구현과 디버깅의 간단함에 있다. 층들은 단지 자신의 하위 층들의 서비스와 기능(연산)들만을 사용하도록 선택된다. 이러한 접근 방법은 시스템의 검증과 디버깅 작업을 단순화한다. 첫 번째 층은 정의에 의해 하드웨어만을 사용하여 이 층의 기능을 구현하기 때문에 나머지 시스템에 아무런 신경을 쓰지 않고 디버깅할 수 있다.

image
계층 구조의 운영체제

계층적 접근 방법의 어려운 점은 여러 층을 적절히 정의하는 것, 다른 유형의 구현 방법보다 효율성이 낮다는 것이다. 각 층은 시스템 호출에 오버헤드를 추가하며 그 결과 계층적 구조가 아닌 시스템보다 시스템 호출의 실행시간이 더 오래 걸리게 된다.

2.7.3 마이크로커널

마이크로커널은 통신 설비 외에 추가로 최소한의 프로세스와 메모리 관리를 제공한다. 마이크로커널의 주 기능은 클라이언트 프로그램과 역시 사용자 공간에서 실행되는 다양한 서비스 간에 통신 설비를 제공하는 것이다. 예를 들어 클라이언트 프로그램이 파일에 접근하기 원하면 파일 서버와 상호작용한다. 클라이언트 프로그램과 서비스는 직접 상호작용하지 않는다.

마이크로커널 접근법의 장점은 운영체제의 확장이 용이하다는 것이다. 새로운 서비스는 사용자 공간에 추가되며, 커널의 변경을 필요로 하지 않는다. 마이크로커널은 대부분의 서비스가 커널이 아니라 사용자 프로세스로 실행되기 때문에 보다 높은 보안성과 신뢰성도 제공한다. 만일 한 서비스가 잘못되더라도 운영체제의 다른 부분은 아무런 영향을 받지 않는다.

하지만 마이크로커널은 가중된 시스템 동작 오버헤드 때문에 성능이 감소된다.

2.7.4 모듈

모듈화 커널을 만들기 위해 운영체제를 설계하는 가장 좋은 기술은 객체지향 프로그래밍 기법을 사용하는 것이다. 이 접근법에서 커널은 핵심적인 구성요소의 집합을 가지고 있으며 부팅 때 또는 실행 중에 부가적인 서비스들을 링크한다.

이런 설계는 핵심 서비스를 제공할 수 있게 할 뿐 아니라 특정 기능들을 동적으로 구현할 수 있게 한다. 예를 들어 특정 하드웨어를 위한 장치와 버스 드라이버는 커널에 추가될 수 있고 다른 파일 시스템도 적재가능 모듈을 이용하여 지원될 수 있다.

image
Solaris 적재 가능 모듈

전체적인 결과는 커널의 각 부분이 정의되고 보호된 인터페이스를 가진다는 점에서 계층적 구조를 닮았다. 그러나 모듈은 임의의 모듈을 호출할 수 있다는 점에서 계층적 구조보다 유연하다. 게다가 중심 모듈은 단지 핵심 기능만을 가지고 있고 다른 모듈의 적재 방법과 모듈들과 어떻게 통신하는지 안다는 점에서는 마이크로 커널과 유사하다. 그러나 통신하기 위해 메시지 전달을 호출할 필요가 없기에 더 효율적이다.

2.8 가상기계

2.7.2에서 설명한 계층적 접근 방법은 가상기계의 개념에서 그 논리적인 결론을 맺는다. 가상기계의 기본적인 착상은 한 컴퓨터의 하드웨어를 추상화하여 다수의 다른 실행 환경을 제공하도록 하는 것이다. 그렇게 개별적인 실행 환경이 자신만의 개별적인 컴퓨터를 사용하는 환상을 만들어낸다.

image
시스템 모델
2.8.1 역사

가상기계는 상업적으로 IMB 메인프레임에서 VM 운영체제를 시초로 등장했다.

2.8.2 장점

가상기계를 만드는데 그 이유는 동일한 하드웨어를 공유하며 다수의 다른 실행 환경(즉 운영체제)을 동시에 실행할 수 있다는 점과 연관된다.

한 가지 중요한 장점은 가상기계들끼리 서로 보호되는 것처럼 호스트 시스템도 가상기계들로부터 보호된다.

2.8.3 모의실험

(밑은 다음에 정리한다.)

2.8.4 반가상화
2.8.5 구현
2.8.6 사례들
2.8.6.1 VMWare
2.8.6.2 자바 가상기계

2.9 운영체제 디버깅

2.9.1 고장 분석
2.9.2 성능 조정
2.9.3 DTrace

2.10 운영체제 생성

2.11 시스템 부트

2.12 요약

운영체제는 여러 가지 서비스를 제공한다. 최하위 수준에서는 실행 중인 프로그램이 시스템 호출을 통해 운영체제에게 직접 요청하도록 허용한다. 높은 수준에서는 명령 해석기 또는 셸이 사용자가 프로그램을 작성하지 않고 요청할 수 있는 기법을 제공한다.

운영체제는 매우 크기 때문에 모듈화가 중요하다. 일련의 계층으로 시스템을 설계하거나 또는 마이크로커널을 사용하는 것이 좋은 기법으로 간주된다.

가상기계의 개념은 계층적 접근 방식을 취하며, 운영체제의 커널과 하드웨어 모두를 마치 전부 하드웨어인 것처럼 취급된다. 다른 운영체제들조차 이 가상기계 위에 적재될 수 있다.

운영체제 설계 과정을 할 때, 정책 결정을 구현의 상세(기법)와 분리하도록 주의해야한다. 후에 정책 결정이 변경되어야 할 때 이런 분리는 최대의 융통성을 제공한다.

comments powered by Disqus