2. Operating System Structures

운영 체제는 프로그램이 실행되는 환경을 제공한다. 이는 여러 관점으로 볼 수 있는데, 한 관점은 시스템이 제공하는 서비스, 하나는 사용자와 프로그래머를 위한 인터페이스, 나머지는 그 요소들 및 그들간의 연결이다.

2.1. Operating-System Services

운영 체제는 프로그램이 실행되는 환경을 제공하며, 프로그램 및 그 사용자들에게 특정 서비스들 사용 가능하게 한다. 이들의 종류는 다음과 같다.

  • 유저 인터페이스. 거의 대부분의 운영 체제는 유저 인터페이스를 가진다. 대개 그래픽 유저 인터페이스(GUI)가 쓰인다. 모바일 시스템은 터치스크린 인터페이스를 가진다. 다른 옵션은 커맨드라인 인터페이스이다.
  • 프로그램 실행. 시스템은 프로그램을 메모리에 로드하고 실행할 수 있어야 하며 프로그램은 자신의 실행을 종료할 수 있어야 한다.
  • 입출력 동작. 실행 중인 프로그램은 입출력을 요구할 수 있는데, 입출력 디바이스는 운영 체제에 의해 제어된다.
  • 파일시스템 관리. 운영체제는 파일과 디렉토리를 읽고 쓸 수 있도록 파일시스템을 제공해야 한다.
  • 통신. 한 프로세스가 다른 프로세스와 정보를 교환해야 할 때가 있다. 이는 공유 메모리메시지 패싱으로 구현될 수 있다.
  • 에러 감지. 운영 체제는 항상 에러를 감지하고 수정할 수 있어야 한다.

다른 기능들은 사용자를 돕는 것이 아니라 운영 체제 자체의 효율성을 위해 존재한다.

  • 자원 할당. 동시에 동작하는 복수의 프로세스가 있을 때, 자원은 각각 할당되어야 하며 운영 체제는 이를 관리할 수 있어야 한다.
  • 로깅. 어떤 프로그램이 컴퓨터 자원을 얼마나 쓰는지 추적해야 한다.
  • 보호 및 보안. 다수 사용자를 갖는 시스템의 정보의 소유자는 그 정보의 사용을 제어하길 원할 수 있으며, 운영 체제는 이에 대한 수단을 제공해야 한다.

2.2. User and Operating-System Interface

운영 체제가 사용자와 상호작용하기 위한 인터페이스에는 크게 세 가지가 있다. 커맨드 인터프리터, GUI, 터치스크린 인터페이스이다.

2.2.1. Command Interpreters

대부분의 운영 체제들은 이라는 커맨드 인터프리터를 내장한다. 이의 기본 기능은 다음 사용자 정의 명령어를 받아 실행하는 것이다. 한 방식에서는 커맨드 인터프리터 그 자신이 커맨드를 실행하는 코드를 포함하는 경우도 있다. 다른 방식에서는 커맨드의 동작을 시스템 프로그램을 통해 구현한다.

2.2.2. Graphical User Interface

운영 체제와 상호작용하는 두 번째 방식은 유저 친화적 그래픽 유저 인터페이스, GUI를 통한 것이다. 대개 사용자들은 데스크톱으로 특정되는 윈도우-메뉴 시스템을 차용한다. 사용자는 마우스를 프로그램이나 폴더아이콘에 올려 이를 실행한다. GUI는 역사에 따라 여러 번 바뀌어 왔다. 전통적으로 UNIX 시스템은 커맨드 라인 인터페이스를 기반으로 하나 GUI 사용도 가능하다.

2.2.3. Touch-Screen Interface

모바일 기기는 터치 스크린 인터페이스를 쓴다. 사용자들은 터치 스크린에 제스처를 통해 상호작용한다. iPad와 iPhone은 Springboard 터치 인터페이스를 쓴다.

2.2.4. Choice of Interface

CLI와 GUI 중 무엇을 쓸 지는 취향의 문제이다. 시스템 운영자들과 파워 사용자들은 대개 CLI를 사용한다. 쉘 스크립트 등의 기능을 이용해 반복적인 작업을 쉽게 수행할 수 있기 때문이다. 그 반대로, 대부분 윈도우 유저들은 윈도우 GUI 환경에 익숙하다. iOS나 안드로이드 모바일 시스템에도 CLI가 있지만 잘 쓰이지 않는다. UI는 시스템에 따라 다르고 시스템을 쓰는 사용자에 따라서도 다르지만, 대개 실제 시스템 구조와는 분리된다.

2.3. System Calls

시스템 호출은 운영 체제에서 사용 가능한 서비스에 대한 인터페이스를 제공한다.

2.3.1. Example

간단한 예를 보자. 파일을 복사하는 방법은 cp in.txt out.txt 등으로 커맨드를 입력할 수도 있고 다른 방법으로는 프로그램에게 사용자에 이름을 묻게 하는 것이다. 어쨌든 파일 이름들을 입력받은 후에 프로그램은 입력 파일을 열어 출력 파일을 생성해야 한다. 이는 각각의 시스템 호출을 포함한다. 가능한 에러 조건도 대응되어야 하며, 이것도 시스템 호출로 이루어진다. 두 파일이 세팅된 후에는 시스템 호출을 통해 파일의 내용을 복사한다. 정상적으로 이루어졌다면 시스템 호출을 통해 두 파일을 닫고 유저에게 이를 알린다.

2.3.2. Application Programming Interface

간단한 프로그램도 운영 체제의 시스템 호출을 많이 사용하지만, 애플리케이션 제작자들은 애플리케이션 프로그래밍 인터페이스(API)를 통해 이보다 높은 수준에서 추상화된 인터페이스를 다룬다. UNIX나 Linux의 경우 C로 쓰여진 프로그램이 호출하는 운영체제의 라이브러리는 libc라 불린다. 이러한 API들은 실행되었을 시 애플리케이션 프로그래머를 위한 시스템 호출을 수행한다. 애플리케이션 제작자들이 API를 선호하는 이유는 포터블함과 사용의 용이성을 위한 것이다. 시스템 호출을 다루는 데 있어 다른 중요한 요소는 런타임 환경(RTE)으로, 특정 프로그래밍 언어로 쓰여진 애플리케이션을 실행하기 위한 소프트웨어들의 집합이다. 컴파일러, 인터프리터, 라이브러리, 로더 등. 이는 운영 체제에 의해 제공되는 시스템 호출에 대한 연결을 수행하는 시스템 호출 인터페이스를 제공한다. 이 때 호출자는 시스템 호출이 어떻게 구현되었는지, 그것이 무엇을 하는지 알 필요 없이 API만 따르면 된다. 시스템 호출은 쓰는 컴퓨터에 따라 다르게 발생한다.

운영 체제에 매개변수를 넘기는 방법에는 크게 3가지가 있다. 첫째는 레지스터에 파라미터를 넘기는 방법. 이외에는 메모리 상 블록에 파라미터를 저장한 뒤 그 블록의 주소를 레지스터에 넘겨주는 방법. 또는 프로그램의 스택푸시된 뒤 하는 방법.

2.3.3. Types of System Calls

시스템 호출은 크게 6종류가 있다. 프로세스 제어, 파일 관리, 디바이스 관리, 정보 유지보수, 통신, 보안.

2.3.3.1. Process Control

프로그램이 비정상적으로 종료되었을 경우 종종 그 메모리의 덤프가 복제되어 버그를 해결할 수 있도록 디버거가 도와 준다.

프로그램을 실행하는 프로세스는 다른 프로그램을 실행하거나 로딩할 수도 있다. 이는 커맨드 인터프리터가 프로그램을 실행하는 것을 가능케 한다. 새 프로그램이 종료되면 원래 프로그램으로 제어가 반환되며 이 때 원래 프로그램의 메모리 이미지가 저장되어야 한다. 동시에 실행될 경우도 있다.

운영 체제는 새 프로세스(들)을 만들 때 그 실행을 제어할 수도 있어야 한다. 그리고 그 실행이 끝날 때까지 대기할 수도 있어야 한다. 프로세스간 데이터가 공유될 경우 이를 하는 기능도 있어야 한다.

단일 태스킹 시스템으로 아두이노의 예를 들어보면, PC에서 프로그램을 쓴 뒤 컴파일된 스케치에 이를 올린다. 이 때 부트로더가 이를 아두이노의 메모리의 특정 영역에 올려 실행한다. 멀티 태스킹 시스템의 예로는 FreeBSD 등이 있다. 이는 다른 프로그램이 실행될 때에도 커맨드 인터프리터가 실행을 지속할 수 있다.

2.3.3.2. File Management

파일 시스템을 다루는 여러 공용 시스템 호출이 있다. 이는 파일이나 디렉토리의 생성과 삭제, 특성 제어 등을 수행한다.

2.3.3.3. Device Management

프로세스는 실행에 있어 여러 자원을 필요로 할 수 있다. 운영 체제에 의해 관리되는 자원을 디바이스로 볼 수 있으며 운영 체제는 이의 할당을 제어한다. UI상에서 파일과 디바이스를 비슷하게 다룰 수도 있다.

2.3.3.4. Information Maintenance

많은 시스템 호출은 시간, 날짜 등의 정보를 단순히 전달하기도 한다. 싱글 스텝 모드 등의 다른 시스템 호출은 디버깅을 도와주기도 한다. 또는 프로그램 실행의 시간 프로파일링을 하기도 한다. 이 때 운영 체제는 실행하는 프로세스의 정보를 저장한다. 이 때도 시스템 호출이 쓰인다.

2.3.3.5. Communication

프로세스간 통신에는 크게 2종류가 있다.

메시지 전송 모델은 프로세스들은 메시지를 교환해 정보를 전송한다. 이 때 네트워크가 가진 호스트명과 프로세스가 가진 프로세스명으로 통신의 대상을 특정한다. 이를 보조하기 위해 특정한 목적의 데몬이 쓰이며, 이를 통해 클라이언트서버가 메시지를 교환한다.

공유 메모리 모델에서는 프로세스간 공유되는 메모리 영역에 읽고 쓰기를 통해 프로세스간 통신이 이루어진다.

대다수의 운영 체제는 두 모델을 모두 구현한다. 메시지 전송은 소용량 정보 전송에, 공유 메모리는 속도를 위해 쓰인다.

2.3.3.6. Protection

보안은 컴퓨터 시스템에 제공되는 자원에 대한 접근을 제어한다. 이에는 퍼미션이 쓰인다.

2.4. System Services

시스템 서비스(시스템 유틸리티)는 프로그램 개발과 실행을 위한 편리한 환경을 제공한다. 이에는 다음 종류들이 있다.

  • 파일 관리. 파일과 디렉토리의 관리.
  • 상태 정보. 동작 환경의 상태에 대한 정보. 어떤 시스템은 설정 정보를 담는 레지스트리를 지원하기도 한다.
  • 파일 수정. 파일을 수정할 수 있는 텍스트 에디터.
  • 프로그래밍 언어 지원. 여러 프로그래밍 언어들을 위한 컴파일러, 어셈블러, 디버거, 인터프리터.
  • 프로그램 로드와 실행. 프로그램이 컴파일되면 실행되기 위해서는 메모리에 올려져야 한다.
  • 통신. 프로세스, 사용자, 컴퓨터 시스템간 가상 연결을 만드는 메커니즘을 제공한다.
  • 백그라운드 서비스. 끊임없이 실행되는 시스템 프로그램 프로세스들. 서비스, 서브시스템, 데몬이라고도 한다.

시스템 프로그램과 함께, 대다수의 운영 체제들은 웹 브라우저, 워드 프로세서 등의 애플리케이션 프로그램을 탑재한다. 운영 체제의 관점은 보통 애플리케이션과 시스템 프로그램에 의해 보여지고 실제 시스템 호출의 관점으로 보여지지는 않는다.

2.5. Linkers and Loaders

프로그램은 바이너리 실행 파일로 존재하며 이것이 가동되려면 메모리 상에 놓여져야 한다. 오브젝트로 컴파일된 소스 파일은 재배치 가능한 오브젝트 파일의 포맷으로 물리적 메모리 주소에 놓여진다. 이후, 링커가 이들을 단일 바이너리 실행 파일로 만든다. 로더가 이를 메모리에 로딩한다. 이 과정을 재배치라 한다.

실제로는 대부분의 시스템이 프로그램을 로딩된 이후 동적으로 라이브러리를 연결할 수 있도록 한다. 윈도우는 동적 연결 라이브러리(DLL)를 지원한다. 이는 조건적으로 라이브러리를 연결할 수 있도록 해 준다.

오브젝트 파일과 실행 파일은 컴파일된 머신 코드와 심볼 테이블을 포함하는 표준 포맷을 가진다. UNIX와 Linux 시스템에서는 이를 실행 링크 가능한 포맷(ELF)라 한다. 윈도우는 포터블 실행 파일(PE) 포맷을, macOS는 Mach-O 포맷을 쓴다.

2.6. Why Applications Are Operating-System Specific

한 운영 체제에서 컴파일된 애플리케이션은 기본적으로 다른 운영 체제에서 실행하는 것이 불가능하다. 하지만 가능한 애플리케이션도 있다. 어떻게 그것이 가능할까?

  1. Python이나 Ruby같은 복수의 운영 체제에서 인터프리터가 탑재된 인터프리터 언어로 쓰여져 있기 때문에.
  2. Java같은 애플리케이션을 가상 기기 안에서 실행하는 언어로 쓰여져 있기 때문에. 이 때 자바 가상 머신에 의해 런타임 환경이 포팅된다.
  3. 컴파일러가 기기 또는 운영 체제에 따른 바이너리를 생성해 주는 표준 언어나 API로 쓰여져 있기 때문에.

실제로는 운영 체제에 따른 API를 호출한다던가 문제로 운영 체제간 포팅이 되지 않는 애플리케이션이 많다. 이외에도 다음과 같은 저수준 문제점도 있다.

  • 각 운영 체제의 헤더, 명령어, 변수의 레이아웃을 결정하는 바이너리 포맷이 다를 경우.
  • CPU들이 서로 다른 명령어 집합을 가지는 경우.
  • 특정한 동작의 수행을 위해 운영 체제마다 필요한 시스템 호출이 다른 경우.

이를 부분적으로 해결하기 위한 여러 접근법이 있다. 아키텍쳐 레벨에서는 애플리케이션 바이너리 인터페이스(ABI)가 바이너리 코드의 다른 부분들이 특정 아키텍쳐 내의 특정 운영 체제와 어떻게 상호작용하는지를 정의한다.

이러한 여러 차이점들을 해결하지 않으면 애플리케이션은 다른 운영 체제에서 동작할 수 없다.

2.7. Operating-System Design and Implementation

운영 체제를 설계하고 구현하는 데 있어 문제점들을 살펴보자.

2.7.1. Design Goals

시스템을 설계하는 데 있어 문제는 목표와 명세서를 정의하는 것이다. 요구 사항들은 크게 두 가지로 나눌 수 있다: 사용자 목표시스템 목표. 사용자들은 시스템이 사용하기 편하고, 배우기 쉽고 빠르고 안전한 운영체제를 원할 것이다. 비슷한 목표들이 개발자들에게도 적용된다. 그러나 이를 위한 유일한 해결책은 없다. 운영 체제를 설계하고 특정하는 일은 매우 창조적인 일로, 소프트웨어 공학의 중요한 요소 중 하나이다.

2.7.2. Mechanisms and Policies

하나의 중요한 원칙은 단위전략메커니즘과 분리하는 것이다. 단위전략은 무엇을 할 지를 결정하는 것이고 메커니즘은 어떻게 할 지를 결정한다. 이를 분리하는 것은 유연한 개발을 위해 중요하다. 마이크로커널 기반 운영 체제들은 이를 잘 이행한다. 비슷한 비교를 상업용 운영 체제와 오픈 소스 운영 체제간에 할 수도 있다. 단위전략 결정은 자원 할당에 중요하다.

2.7.3. Implementation

운영 체제를 설계했으면 구현해야 한다. 초기 운영 체제들은 어셈블리어로 쓰여졌으나 이제는 C나 C++같은 고수준 언어로 쓰인다. 이는 코드 작성이 더 빠르고 더 컴팩트하고 이해하고 디버깅하기 쉽다는 이점을 가진다. 단점은 속도의 감소나 더 많은 메모리 사용 등이 있는데 요즘은 컴파일러 최적화가 잘 되어 그리 중요하지는 않다. 운영 체제 내의 성능 개선은 좋은 자료 구조나 알고리즘의 선택이 더 중요하다.

2.8. Operating-System Structure

현대 운영 체제와 같이 크고 복잡한 시스템은 주의 깊게 구조화되어야 한다. 이 컴포넌트들은 어떻게 연결되어 있을까?

2.8.1. Monolithic Structure

가장 간단한 방법은 따로 구조화하지 않는 단일 구조이다. 오리지널 UNIX 운영 체제나 Linux 운영 체제가 단일 커널을 사용한다. 그러나 이 커널 자체도 모듈화된 설계를 갖고 있다. 이는 간단해 보이지만 구현하고 확장하기는 어렵다. 하지만 성능상의 이점은 있다.

2.8.2. Layered Approach

단일 구조 접근법은 강하게 연결된 시스템이라고도 한다. 그 대신 느슨하게 연결된 시스템을 생각해 볼 수 있다. 이는 한 컴포넌트의 변화가 그 컴포넌트에만 영향을 주고, 시스템 구성과 변경에 있어 자유도가 더 높아진다는 장점이 있다.

이런 모듈화의 방식 중 하나는 계층화 접근법이다. 가장 아래 층이 하드웨어고 가장 위 층이 UI이다. 운영 체제 층은 그 사이에 위치하여 특정 자료 구조들과 더 위 층에 의해 실행될 수 있는 함수들로 구성된다. 이 접근법의 이점은 만들기 쉽고 디버깅하기 쉽다는 것이다. 각 층들은 더 아래 층에 의해 제공되는 연산을 통해서만 구현된다. 그 아래층의 연산의 구체적인 구현은 알 필요가 없다. 이러한 접근법은 컴퓨터 네트워크나 웹 애플리케이션에 많이 쓰이지만, 기능 분리의 어려움과 성능상의 문제로 운영 체제에서는 잘 쓰이지 않는다.

2.8.3. Microkernels

1980년 중반에 CMU의 연구자들은 Mach라는 운영 체제를 개발해 모듈화된 마이크로커널 접근법을 차용했다. 이의 주된 기능은 클라이언트 프로그램과 사용자 공간에서 구동되는 서비스간 통신을 제공한다. 마이크로커널 접근법의 한 이점은 운영 체제의 확장을 쉽게 한다는 것이다. 이의 가장 널리 알려진 구현은 Darwin일 것이다. 또 다른 예로 QNX도 있다. 하지만 역시 성능 상의 문제가 있다.

2.8.4. Modules

다른 접근법으로 로더블 커널 모듈(LKMs)이 있다. 여기서 커널은 코어 컴포넌트의 집합과 모듈화된 추가 서비스들이 부팅 타임 또는 런타임에 연결된다. 이는 UNIX나 Windows의 현대적인 구현 방식에서 널리 쓰인다.

이 설계의 발상은 커널은 핵심 서비스만 제공하도록 하고 다른 서비스는 커널이 구동될 때 동적으로 구현되도록 하는 것이다. 이는 계층화 시스템과 비슷하나 계층화 시스템보다 유연하다. 모듈이 임의의 다른 모듈을 호출할 수 있기 때문이다. 또한 마이크로커널 시스템과 비슷하나 성능 상으로 더 좋다. Linux는 디바이스 드라이버나 파일 시스템을 지원하는 데 있어 로더블 커널 모듈을 사용한다.

2.8.5. Hybrid Systems

실제로는 단일한 종류의 정적인 구조만을 차용하는 운영 체제는 거의 없고, 여러 구조들을 결합한다.

2.8.5.1. macOS and iOS

애플의 macOS는 데스크탑과 랩탑 컴퓨터 시스템에서, iOS는 스마트폰과 태블릿에서 구동되는 운영 체제이다. 이들은 다음으로 계층화되어 있다.

  • 사용자 경험 계층. 이는 사용자가 디바이스와 상호 작용하는 UI를 정의한다.
  • 애플리케이션 프레임워크 계층. 이는 Objective-C나 Swift 프로그래밍 언어들을 위한 API를 제공한다.
  • 핵심 프레임워크. 이 계층은 그래픽이나 미디어를 지원하는 프레임워크를 정의한다.
  • 커널 환경. 이는 Darwin으로도 알려져 있다.

애플리케이션들은 UX 계층을 통할 수도 있고 직접적으로 하위 계층들과 상호작용할 수도 있다.

macOS와 iOS의 핵심적 차이들은 다음과 같다:

  • 데스크탑/랩탑과 모바일이라는 차이 때문에, macOS는 인텔 아키텍쳐에서 컴파일되고, iOS는 ARM 기반 아키텍쳐에서 컴파일된다. iOS의 보안이 더 강하다.
  • iOS가 훨씬 더 제약이 심하다.

이제 계층화된 시스템인 Darwin 이야기를 해 보자. Darwin은 대다수의 운영 체제와는 달리 2가지의 시스템 호출 인터페이스를 가진다. Mach 시스템 호출 (트랩)들과 BSD 시스템 호출 (POSIX 기능을 제공한다). 시스템 호출 인터페이스 아래에는 기본적 운영 체제 서비스, 예컨대 메모리 관리, CPU 스케쥴링, 프로세스간 통신 등을 제공한다. 이는 커널 추상화를 통해 제공되는 경우가 많다. Mach와 BSD 외에도 커널 환경은 디바이스 드라이버나 동적 로드 가능한 모듈 (커널 확장 또는 kexts)들을 제공한다. 성능의 저하를 막기 위해 Darwin은 이들 셋을 단일 주소 공간에 배치한다. Apple은 이를 오픈 소스로 릴리즈했다.

2.8.5.2. Android

안드로이드 운영 체제는 오픈 핸드셋 얼라이언스에 의해 설계되어 안드로이드 스마트폰과 태블릿 PC등을 위해 개발되었다. 이는 계층화된 관점에서 iOS와 비슷하다.

안드로이드 기기를 위한 소프트웨어 개발자는 Java 언어로 애플리케이션을 개발하지만 표준 Java API 대신 안드로이드 API를 쓴다. 많은 자바 가상 머신이 저스트-인-타임 컴파일을 수행하지만, 안드로이드 런타임은 어헤드-오브-타임(AOT) 컴파일을 수행해 안드로이드 런타임에서 실행될 수 있는 네이티브 기계 코드로 바꾼다. 안드로이드 개발자들은 자바 네이티브 인터페이스(JNI)를 이용해 Java 프로그램을 쓰는 것도 가능하다. JNI를 사용한 프로그램은 대개 다른 하드웨어로 포팅이 불가능하다.

안드로이드 애플리케이션에 사용 가능한 네이티브 라이브러리들은 웹 브라우저, 데이터베이스, 네트워크 등을 위한 개발 프레임워크 등을 포함한다. 안드로이드가 구동될 수 있는 하드웨어 기기의 수는 거의 제한이 없기 때문에 구글은 물리적 하드웨어를 하드웨어 추상화 계층으로 추상화했다. Linux에 쓰이는 표준 C 라이브러리는 glibc이지만 구글이 안드로이드에 쓰는 표준 C 라이브러리는 Bionic이다. 이는 메모리, 속도, 라이선스 면에서 이점이 있다. 최하위 계층은 리눅스 커널이다.

2.9. Building and Booting an Operating System

운영 체제를 설계하고 구현할 때에는 여러 설정과 여러 기기에서도 쓸 수 있도록 하는 것이 바람직하다.

2.9.1. Operating-System Generation

대개 새로 구입하는 컴퓨터에는 운영 체제가 탑재되어 있지만, 그렇지 않을 때는 운영 체제를 설치해야 한다. 운영 체제를 처음부터 만들려면 소스 코드를 작성하고, 운영 체제를 설정하고, 컴파일하고, 설치한 뒤 부팅해야 한다. 이 때 시스템을 설정하는 것은 어떤 특성들이 포함될지를 결정하는 것을 포함한다. 이를 적절히 변경해서 전체 시스템 빌드를 재수행하여 커스터마이징할 수도 있다. 덜 맞춤된 관점에서는, 시스템 설정은 존재하는 라이브러리로부터의 미리 컴파일된 오브젝트 모듈을 선택하도록 할 수 있다. 다른 면에서는, 완전히 모듈화된 시스템을 구성하는 것도 가능하다.

이런 접근법들간의 주된 차이는 생성된 시스템의 크기, 일반성, 유지보수의 용이성 등이다. 임베디드 시스템에서는 특정한 하드웨어 설정을 위한 운영 체제를 만드는 접근이 드물지 않으나 대다수의 현대 운영 체제는 모듈화된 관점도 차용한다.

Linux 시스템도 처음부터 만들 수 있는데, 소스 코드를 받고 커널을 설정한 뒤 메인 커널과 커널 모듈을 컴파일하고, 이를 설치한 뒤 재부팅하면 된다. 또는 리눅스 가상 머신을 설치함으로써 존재하는 시스템을 변경할 수도 있다. 이에는 여러 방법이 있다.

2.9.2. System Boot

운영 체제가 만들어졌으면 하드웨어에 의해 사용 가능해져야 한다. 이는 시스템 부팅을 통해 이뤄진다. 먼저 부트스트랩 또는 부트로더가 커널을 배치하고 커널이 가동된 뒤 하드웨어를 초기화하고 루트 파일 시스템이 마운트된다.

어떤 컴퓨터 시스템들은 다단계 부팅 과정을 가직도 한다. 컴퓨터가 처음 켜질 때 BIOS가 구동되어 부트 블록을 로딩한다. 최근 컴퓨터 시스템은 BIOS 기반 부트 프로세스를 UEFI (통합된 확장 가능한 펌웨어 인터페이스)로 교체하였다. 이는 64비트 시스템 지원과 대형 디스크에 대한 지원이라는 강점이 있고, 단일 단계라서 부팅도 더 빠르다.

BIOS건 UEFI건, 부트스트랩은 커널을 로딩하는 것 뿐만 아니라 기기의 상태를 진단하고 초기화할 수도 있다. 이것이 다 완료된 후에야 시스템이 구동된다고 하는 것이다.

GRUB은 Linux와 UNIX 시스템을 위한 오픈 소스 부트스트랩 프로그램이다. 공간을 절약하기 위해 Linux 커널 이미지는 압축되어 있으며 메모리에 올려진 후에야 압축이 해제된다. 부팅 메커니즘은 부트로더와 독립적이지 않기 때문에, 펌웨어는 어떤 부트로더를 써야 할지를 알고 있어야 한다.

모바일 시스템에 대한 부팅 과정은 일반적인 PC와는 조금 다르다. 가장 잘 알려진 안드로드 부트 로더는 LK이다. Linux와 다르게, Android는 initramfs를 계속 유지한다.

마지막으로, 대다수 운영 체제의 부트로더들은 복원 모드단일 사용자 모드를 지원하여 하드웨어 문제 등을 진단하거나, 파일 시스템의 훼손을 복구하거나, 운영 체제의 재설치도 가능케 한다.

2.10. Operating-System Debugging

디버깅은 하드웨어나 소프트웨어의 에러를 찾아 고치는 일이다. 이는 성능 튜닝과 성능 병목 제거를 포함한다.

2.10.1. Failure Analysis

프로세스가 실패하면 대다수 운영 체제들은 에러 정보를 로그 파일에 남긴다. 또는 코어 덤프를 참조할 수도 있다. 큰 프로그램을 디버깅하는 것은 어려운데, 커널의 경우는 더욱 그렇다. 커널의 실패는 크래시라 불리며, 이 때 메모리 상태가 크래시 덤프로 저장된다. 운영 체제 디버깅과 프로세스 디버깅은 다른 도구와 테크닉을 사용한다.

2.10.2. Performance Monitoring and Tuning

운영 체제는 시스템 동작을 측정하고 시각화할 수 있어야 한다. 이를 위해 카운터와 트레이싱을 할 수 있다.

2.10.2.1. Counters

운영 체제는 시스템 동작을 여러 카운터를 통해 추적할 수 있다. 시스템 호출의 수, 어떤 네트워크 디바이스에 대한 동작의 수 등. Linux 시스템에는 ps, top, vmstat, netstat, iostat 등이 있다. 이는 대개 /proc 파일 시스템 내에 존재한다. Windows 시스템은 윈도우 작업 관리자를 제공한다.

2.10.3. Tracing

카운터는 특정한 통계량에 대한 현재 값을 알아내는 반면, 트레이싱 도구는 특정 이벤트에 대한 데이터를 모은다. Linux 시스템에는 strace, gdb, perf, tcpdump 등이 있다. 이를 쉽게 하는 것은 왕성한 연구 분야이다.

2.10.4. BCC

유저 레벨과 커널 코드간의 상호 작용을 디버깅하는 건 상호작용을 조사하고 두 코드 전부를 이해하는 도구들 없이는 거의 불가능하다. BCC는 이러한 도구들 중 하나로 Linux 시스템의 특징을 트레이싱하는 도구 모음이다. 이는 eBPF의 프론트엔드 인터페이스로서 이들은 증명기를 거쳐 Linux 커널에 삽입된다. eBPF는 C로 쓰여져 있어서 인터페이스 활용이 어려웠지만 BCC는 Python 인터페이스를 차용해 활용을 쉽게 하였다. BCC 패키지는 가동되는 Linux 커널의 여러 영역을 모니터링할 수 있다. 이가 제공하는 많은 도구들은 특정 목적에 쓰일 수도 있다. BCC는 보안성 및 신뢰성 면에서 검증되어 있다는 것이 강점이다.

2.11. Summary

  • 운영 체제는 사용자와 프로그램에 서비스를 제공함으로써 프로그램의 실행 환경을 제공한다.
  • 운영 체제와 상호작용하는 3개의 주된 방법은 커맨드 인터프리터, 그래픽 사용자 인터페이스, 터치스크린 인터페이스이다.
  • 시스템 호출은 운영 체제에 의해 제공된 서비스들에 대한 인터페이스를 제공한다. 프로그래머들은 시스템 호출의 API를 사용해 시스템 호출 서비스에 접근한다.
  • 시스템 호출은 6종류로 나눌 수 있는데, 프로세스 제어, 파일 관리, 디바이스 관리, 정보 유지보수, 통신, 보안이다.
  • 표준 C 라이브러리는 UNIX와 Linux 시스템에 대한 시스템 호출 인터페이스를 제공한다.
  • 운영 체제는 사용자운영 체제는 사용자와 프로그램에 서비스를 제공함으로써 프로그램의 실행 환경을 제공한다.
  • 운영 체제와 상호작용하는 3개의 주된 방법은 커맨드 인터프리터, 그래픽 사용자 인터페이스, 터치스크린 인터페이스이다.
  • 시스템 호출은 운영 체제에 의해 제공된 서비스들에 대한 인터페이스를 제공한다. 프로그래머들은 시스템 호출의 API를 사용해 시스템 호출 서비스에 접근한다.
  • 시스템 호출은 6종류로 나눌 수 있는데, 프로세스 제어, 파일 관리, 디바이스 관리, 정보 유지보수, 통신, 보안이다.
  • 표준 C 라이브러리는 UNIX와 Linux 시스템에 대한 시스템 호출 인터페이스를 제공한다.
  • 운영 체제는 사용자가 다용도로 쓸 수 있는 여러 프로그램들을 탑재하기도 한다.
  • 링커는 여러 재배치 가능한 오브젝트 모듈을 단일 바이너리 실행 파일로 결합시킨다. 로더는 실행 파일을 메모리에 로드해 가용 가능한 CPU에 구동될 수 있게 한다.
  • 애플리케이션이 운영 체제 의존적인 데는 여러 이유가 있다. 프로그램 실행 파일에 대한 바이너리 포맷이 달라서이기도 하고, CPU에 대한 명령어 집합들이 달라서이기도, 시스템 호출이 달라서이기도 하다.
  • 운영 체제는 특정한 목표를 갖고 설계된다. 이는 운영 체제의 단위 전략을 궁극적으로 결정한다. 운영 체제는 이런 단위 전략들을 특정한 메커니즘을 통해 구현한다.
  • 단일 구조 운영 체제는 특정한 구조가 없이 모든 기능이 단일한 주소 공간에 로딩되는 단일한 정적 바이너리 파일에 제공된다. 이런 시스템들은 수정하기는 어렵지만 성능 면에서 이점이 있다.
  • 계층화된 운영 체제는 여러 독립적인 계층으로 나뉘어 있으며, 맨 아래 층이 하드웨어 인터페이스고 맨 위 층이 사용자 인터페이스이다. 계층화된 소프트웨어 시스템들이 얼마간의 성공을 거두긴 했지만, 성능 문제로 인해 운영 체제에서는 선호되지 않는다.
  • 운영 체제 설계에 있어 마이크로커널 접근법은 최소 커널만 사용하고 대다수의 서비스는 사용자 레벨 애플리케이션으로 구동된다. 통신은 메시지 패싱으로 이루어진다.
  • 운영 체제 설계에 있어 모듈화된 접근법은 운영 체제 서비스를 모듈을 통해 제공하고 이것들이 런타임에 로딩되거나 제거될 수 있게 한다. 현대의 운영 체제들은 대부분 단일 구조 커널과 모듈의 조합으로 이루어져 있다.
  • 부트로더는 운영 체제를 메모리에 로딩하고 초기화를 수행한 뒤 시스템 구동을 시작한다.
  • 운영 체제의 성능은 카운터나 트레이싱을 통해 모니터링될 수 있다. 카운터는 시스템별 또는 프로세스별 통계량을 모은 것이고, 트레이싱은 운영 체제를 통한 프로그램의 실행을 추적한다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중