728x90
운영체제 공룡책: 2장 Operating - System Structures
2.1 Operating-System Services
운영체제(OS)의 주요 서비스
- 사용자 인터페이스 (User interface): 대부분 GUI 형태의 그래픽 사용자 인터페이스를 제공하지만, 일부는 CLI(Command Line Interface) 또는 터치스크린 인터페이스를 사용한다.
- 프로그램 실행(Program execution): 프로그램을 메모리에 적재하고 실행, 종료할 수 있게 한다.
- 입출력 (I/O) 작업: 파일 및 장치에 대한 입출력을 관리하여 효율성과 보호를 제공한다.
- 파일 시스템 관리(File-system manipulation): 파일과 디렉토리의 생성, 삭제, 검색, 읽기/쓰기와 접근 권한 관리 기능을 지원한다.
- 통신(Communications): 프로세스 간 정보를 공유 메모리 또는 메시지 전달 방식으로 교환할 수 있게 한다.
- 오류 감지(Error detection): CPU, 메모리, I/O 장치, 사용자 프로그램에서 발생하는 오류를 감지하고 처리한다.
시스템 효율성을 위한 기능
- 자원 할당(Resource allocation): 여러 프로세스가 동시에 실행될 때, CPU, 메모리, I/O 등 자원을 효율적으로 배분한다.
- 기록 관리(Logging): 자원 사용량을 기록하여 통계 분석이나 회계 처리에 활용한다.
- 보호와 보안(Protection and security): 사용자 인증, 접근 제어 및 외부 침입 방지를 통해 데이터와 시스템을 보호한다.
2.2 User and Operating-System Interface
운영체제는 사용자와 상호작용할 수 있는 다양한 인터페이스를 제공합니다.
- 명령어 인터프리터 (Command-Line Interface, CLI): 사용자가 직접 명령어를 입력하여 시스템과 상호작용하는 방식이다. UNIX와 Linux에서는 여러 종류의 쉘(shell)을 제공하며, 이를 통해 다양한 파일 조작 명령을 수행할 수 있다. 대부분의 명령어는 시스템 프로그램을 호출하는 방식으로 구현되어, 명령어 추가 시에도 인터프리터 프로그램 수정 없이 새 프로그램 파일만 추가하면 된다.
- 그래픽 사용자 인터페이스 (GUI): GUI는 아이콘, 메뉴, 윈도우 등을 사용해 사용자가 시각적으로 시스템과 상호작용할 수 있게 한다.
- 터치스크린 인터페이스(Touch-Screen Interface): 스마트폰과 태블릿 등 모바일 기기에서 사용되는 인터페이스로, 터치와 제스처를 통해 상호작용한다.
2.3 System Calls
시스템 호출은 운영체제가 제공하는 서비스를 프로그램에서 사용할 수 있게 하는 인터페이스이다.
2.3.1 Example
파일 복사 프로그램을 작성하는 경우 다음과 같은 시스템 호출이 사용된다:
- 파일 이름 입력: 사용자가 복사할 파일과 복사될 파일의 이름을 지정하도록 요청한다. 이를 위해 입력 및 출력 시스템 호출이 필요하다.
- 파일 열기 및 생성: 입력 파일을 열고, 출력 파일을 생성 및 열기 위해 시스템 호출이 사용된다. 오류가 발생할 경우(예: 파일이 없거나 접근이 제한된 경우), 오류 메시지를 출력하고 프로그램을 종료하는 시스템 호출이 필요할 수 있다.
- 파일 읽기 및 쓰기: 입력 파일에서 데이터를 읽고 출력 파일에 쓰는 반복 과정에서 시스템 호출을 통해 각 작업의 상태를 확인한다. 예를 들어, 읽기 중 파일의 끝에 도달하거나 하드웨어 오류가 발생할 수 있다.
- 파일 닫기 및 종료: 파일 복사가 완료되면, 파일을 닫고 프로그램을 정상 종료하기 위한 시스템 호출이 필요하다.
2.3.2 Application Programming Interface
- API(Application Programming Interface)는 응용 프로그램이 운영체제의 시스템 호출에 접근할 수 있도록 해 주는 인터페이스이다.
- API를 사용함으로써 개발자는 시스템 호출을 직접 다루지 않고도 운영체제의 기능을 활용할 수 있으며, 프로그램의 이식성을 높일 수 있다.
- 운영체제는 API의 함수 호출을 가로채 해당하는 시스템 호출을 수행한다. 이를 위해 시스템 호출 인터페이스가 API 함수와 커널 시스템 호출을 연결하는 역할을 한다. 시스템 호출에는 번호가 부여되며, 인터페이스는 이 번호를 참조해 적절한 시스템 호출을 실행하고 그 결과를 반환한다.
- 시스템 호출에 필요한 매개변수는 보통 레지스터에 저장되지만, 매개변수가 많을 경우 메모리 블록을 사용하거나 스택에 쌓아서 전달한다. 이를 통해 매개변수의 개수나 길이에 제한 없이 데이터를 전달할 수 있다.
2.5 Linkers and Loaders
프로그램이 실행되기 위해서는 디스크에 있는 바이너리 실행 파일이 메모리에 로드되어 프로세스 컨텍스트에 배치되어야 한다. 아래는 위 설명의 과정이다.
1. 컴파일: 소스 파일을 컴파일하여 메모리 어느 위치에도 로드할 수 있는 재배치 가능한 객체 파일로 만든다.
2. 링킹:
- 링커는 객체 파일을 하나의 실행 파일로 결합한다. ➡️ 표준 라이브러리와 같은 추가 객체 파일도 포함
- 링킹 과정에서 재배치가 발생한다. ➡️ 프로그램의 코드와 데이터를 실제 메모리 주소와 맞추는 작업입니다.
3. 로딩: 로더가 실행 파일을 메모리에 로드하여 프로세스로 실행할 수 있게 한다.
2.6 Why Applications Are Operating-System Specific
애플리케이션은 운영 체제(OS)별로 다른 시스템 호출 및 하드웨어 구조를 사용하기 때문에, 하나의 OS에서 컴파일된 애플리케이션은 다른 OS에서 실행되지 않는다.
동일 애플리케이션을 여러 OS에서 실행하는 방법
- 인터프리터 사용(interpreted language): Python 같은 인터프리터 언어로 작성하여 다양한 OS에서 실행 가능하게 할 수 있다. 그러나 성능이 저하되고 기능 제약이 있을 수 있다.
- 가상 머신 사용(virtual machine): Java처럼 OS와 독립적으로 실행되는 가상 머신(RTE)을 통해 애플리케이션을 실행할 수 있다. 이 경우도 성능과 기능 제한이 존재한다.
- 표준 API 사용 및 이식성 확보(standard language or API): POSIX API처럼 표준화된 API를 사용하여 다양한 OS에 포팅하는 방식이다. 하지만 이 과정은 많은 시간과 노력이 필요하다.
2.7 Operating-System Design and Implementation
OS 설계와 구현 과정에서 고려사항
- 설계 목표(Design Goals): OS 설계는 하드웨어 선택과 OS의 종류(데스크톱, 모바일, 실시간 등)에 따라 달라진다. 목표는 사용자 요구(편리성, 안전성, 속도)와 시스템 요구(유연성, 신뢰성, 효율성)로 나뉘며, 이것은 OS의 다양한 구현 방식을 유도한다.
- 메커니즘과 정책의 분리(Mechanisms and Policies): 메커니즘은 "어떻게"에 대한 방법을, 정책은 "무엇을" 할지 결정한다. 이 분리는 유연성을 높여 정책 변경이 필요한 경우 메커니즘 수정 없이 적용할 수 있게 한다. 예를 들어, 우선순위 정책을 변경해도 메커니즘 자체를 수정할 필요는 없다.
- 구현 방식(Implementation): 현대 OS는 주로 C와 C++ 같은 Higher-level 언어로 구현되며, 성능이 중요한 일부는 어셈블리어로 작성된다. Higher-level 언어를 사용하면 코드 작성이 빠르고 이해와 디버깅이 용이하며, 이식성이 높아져 다양한 하드웨어에서의 실행이 용이하다.
2.8 Operating-System Structure
- 현대 운영체제(OS)는 복잡하고 규모가 크기 때문에 올바르게 기능하고 쉽게 수정되기 위해 신중하게 설계되어야 한다.
- 일반적인 접근법은 시스템을 하나의 큰 단위가 아닌, 명확한 인터페이스와 기능을 가진 작은 구성 요소(모듈)로 나누는 것이다.
- 코드의 모든 논리를 메인 함수에 두지 않고 여러 함수로 분리해 각 함수의 매개변수와 반환 값을 명확히 하여 메인 함수에서 호출하는 방식과 유사하다.
- 이러한 OS 구성 요소들은 상호 연결되어 커널로 통합됩니다.
2.8.1 Monolithic Structure
- 모놀리식 구조(Monolithic Structure)는 운영체제(OS)의 모든 기능을 하나의 정적 바이너리 파일에 담아 단일 주소 공간에서 실행하는 구조이다.
- UNIX의 초기 버전이 대표적 예로, 커널과 시스템 프로그램으로 구성되어 있으며, 커널은 파일 시스템, CPU 스케줄링, 메모리 관리 등을 포함한 운영체제 기능을 제공한다.
- Linux도 UNIX를 기반으로 유사하게 모놀리식 구조를 가지며, 단일 주소 공간에서 커널 모드로 실행된다. 이 구조는 성능이 뛰어나지만 구현과 확장이 어렵다는 단점이 있다.
2.8.2 Layered Approach
- 레이어 접근법은 운영체제를 여러 계층으로 분할하여 각 계층이 특정 기능만을 수행하도록 하는 방식이다.
- 하위 계층의 기능을 상위 계층에서 호출하며, 하위 계층에 오류가 없으면 상위 계층도 정상 동작할 수 있어 디버깅이 용이하다.
- 각 계층은 하위 계층의 동작만 알면 되므로, 데이터 구조나 하드웨어 세부사항을 감출 수 있다.
- 이 구조는 시스템 구현 및 수정에 용이하지만, 서비스 호출 시 여러 계층을 거치면서 성능 저하가 발생할 수 있다.
2.8.3 Microkernels
- 마이크로커널(Microkernel) 구조는 운영체제에서 필수적인 기능만을 커널에 남기고, 나머지 서비스는 사용자 공간에서 실행되는 독립적인 프로그램으로 구현하는 방식이다.
- 이 구조는 커널을 작게 만들어 관리와 확장을 용이하게 하고, 새로운 서비스 추가 시 커널 수정을 피할 수 있어 시스템 이식성이 높다.
- 대부분의 서비스가 사용자 모드에서 실행되기 때문에 보안과 신뢰성이 향상된다.
- 사용자 공간에 있는 서비스들 간의 메시지 전달 시 성능 저하가 발생할 수 있는 단점이 있다.
2.8.4 Modules
- 로드 가능한 커널 모듈(LKM)은 현대 운영체제 설계에서 가장 효율적인 방법으로, 커널은 핵심 서비스를 제공하고, 추가적인 서비스는 부팅 시 또는 실행 중에 동적으로 로드하여 연결된다.
- 이 방식은 커널을 수정하고 재컴파일하는 대신, CPU 스케줄링이나 메모리 관리와 같은 기본 기능은 커널에 통합하고, 파일 시스템과 같은 추가 기능은 동적으로 로드할 수 있도록 한다.
- 이 접근 방식은 계층 구조와 유사하지만, 모듈 간의 자유로운 호출이 가능하고, 마이크로커널처럼 메시지 전달을 사용하지 않아 더 효율적이다.
2.8.5 Hybrid Systems
대부분의 운영체제는 하나의 고정된 구조를 채택하기보다는 다양한 구조를 결합하여 하이브리드 시스템을 구성한다.
2.8.5.1 macOS and iOS
- Apple의 macOS와 iOS는 비슷한 아키텍처를 가지고 있지만, 용도와 일부 기술적 차이가 있다.
- 두 운영체제는 공통적으로 다층 구조를 채택하며, 주요 계층은 user experience, application frameworks, core frameworks, 그리고 kernel environment (Darwin)으로 나눠진다.
- macOS는 Intel 아키텍처에서 실행되며, iOS는 ARM 아키텍처용으로 설계되었다.
- iOS는 모바일 시스템의 특성상 전력 관리와 메모리 관리가 강화되어 있고, 보안 설정이 더 엄격하다.
- macOS는 개발자가 POSIX와 BSD API에 접근할 수 있지만, iOS는 이러한 접근을 제한한다.
2.8.5.2 Android
- Android는 Google 주도의 Open Handset Alliance에 의해 개발된 오픈 소스 모바일 운영체제이다.
- Android는 iOS와 유사한 계층화된 구조를 가지고 있으며, 그래픽, 오디오, 하드웨어 기능을 지원하는 다양한 프레임워크를 제공한다.
- Android는 하드웨어 추상화 계층(HAL)을 통해 다양한 하드웨어 장치에 대한 일관된 인터페이스를 제공하며, 개발자는 이를 통해 다양한 디바이스에서 실행 가능한 애플리케이션을 개발할 수 있다.
- Android는 또한 Bionic 표준 C 라이브러리를 사용하여 메모리 사용을 최소화하고, 모바일 장치에 최적화된 성능을 제공한다.
- Android의 하단에는 Linux 커널이 있으며, 모바일 시스템의 요구사항에 맞게 전력 관리, 메모리 관리 및 IPC(Binder) 등을 수정하여 사용다.
2.9 Building and Booting an Operating System
2.9.1 Operating-System Generation
운영체제 구축과정
- 운영 체제 소스 코드 작성 또는 획득
- 운영 체제 시스템에 맞게 설정
- 운영 체제 컴파일
- 운영 체제 설치
- 컴퓨터 부팅 및 운영 체제 실행
2.9.2 System Boot
운영 체제 부팅 과정은 컴퓨터가 켜졌을 때 운영 체제가 메모리에 로드되고 실행되도록 하는 단계
- 부트로더 실행: 컴퓨터가 켜지면, BIOS나 UEFI에 저장된 부트로더가 실행된다. 이 부트로더는 운영 체제 커널을 메모리에 로드하는 역할을 한다.
- 커널 로딩 및 실행: 부트로더는 커널을 메모리에 로드하고, 커널이 하드웨어를 초기화한다.
- 루트 파일 시스템 마운트: 커널이 파일 시스템을 마운트하여 시스템을 사용할 준비
- 시스템 시작: 커널은 시스템의 초기 프로세스인 systemd를 시작하고, 이후 다른 서비스를 시작한 뒤 로그인 화면을 표시한다.
2.10 Operating-System Debugging
운영 체제 디버깅은 시스템의 하드웨어와 소프트웨어에서 오류를 찾아 수정하는 과정이다. 주로 프로세스 실패 분석과 성능 모니터링 및 튜닝을 다룹니다.
- 실패 분석(Failure Analysis):
- 프로세스 실패 시, 운영 체제는 로그 파일에 오류 정보를 기록하거나 코어 덤프(프로세스 메모리 상태 저장)를 생성한다.
- 커널 오류는 "크래시"라고 하며, 시스템 재부팅 후 크래시 덤프 파일로 분석한다.
- 성능 모니터링 및 튜닝(Performance Monitoring and Tuning):
- 카운터 기반 도구는 시스템의 활동을 추적한다. 예: 리눅스의 ps, top, vmstat, iostat 등이 있습니다.
- 트레이싱 도구는 특정 이벤트(시스템 호출 등)의 데이터를 수집한다. 예: strace, gdb, perf, tcpdump.
- BCC (BPF Compiler Collection):
- BCC는 리눅스 시스템에서 동적 커널 추적을 위한 도구 모음으로, eBPF(확장된 베르클리 패킷 필터)를 사용하여 시스템 이벤트를 추적한다.
- Python 인터페이스를 제공하여 eBPF 프로그램을 쉽게 작성하고 커널에 삽입할 수 있다. 예: disksnoop.py는 디스크 I/O 활동을 추적합니다.
- BCC는 라이브 시스템에서 성능 모니터링 및 디버깅을 수행할 수 있어, 실시간으로 성능 병목 현상이나 보안 문제를 식별할 수 있다.
여기까지는 교양으로 읽으면 좋을(?)듯 합니다...
728x90
반응형
'운영체제 공룡책' 카테고리의 다른 글
[운영체제 공룡책] 6장 Synchronization Tools(동기화 도구) (1) | 2025.01.02 |
---|---|
[운영체제 공룡책] 5장 CPU Scheduling (2) | 2024.12.14 |
[운영체제 공룡책] 4장 Threads &Concurrency (1) | 2024.11.26 |
[운영체제 공룡책] 3장 ProcessManagement (4) | 2024.11.20 |
[운영체제 공룡책] 1장 Overview (2) | 2024.11.07 |