---
# System prepended metadata

title: 'Operating System Concepts, Ch. 2'

---

# Operating System Concepts, Ch. 2: Operating System Structures
## Services

- Inter-process communication can be achieved by **shared memory** or **message passing**.

## System Calls

- Even a simple copy command may require a series of system calls.
- Arduino is a single-tasking system, as it only allows one sketch to be run at a time.

There are several types of system calls,
1. **Process Control**
    Creation, termination (& exit codes), waiting, event-driven control (e.g. continue when children are done, etc.), **lock** (shared data).
2. **File Management**
    Creation, deletion, R/W, attribute access, etc.
3. **Device Management**
    Resource management, exclusive usage, file-like operations.
4. **Information Maintenance**
    Time, date, memory dumping, etc.
5. **Communication**
    Message passing (& connection establishment, like networking, **food for smaller amount of data**), shared memory.
6. **Protection**
    Resource access control (permission).
    
## Linkers and Loaders

![](https://hackmd.io/_uploads/S1LUPngah.png)

- **Relocatable object files** (object files) are designed to be loaded into arbitraty locations in the memory.
- **Linkers** combine several these files into one binary (static linking).
- **Loaders** then put the binary into the memory to be executed.
- Libraries may be **dynamically linked**, and shared among processes.
- There may be additional symbol tables and metadata in a binary, such as in Linux's **ELF (Executable and Linkable Format)**.
- There are several reasons why it is hard to develop cross-OS applications,
    - Executable structure dictation
    - Different instruction sets
    - System call disparities
- And some methods to do so,
    - Virtual machines
    - High-level interpreted languages
    - Multiple builds
- **Application Binary Interface (ABI)** is the architectural equivalence of APIs. It defines (typically for a given achitecture) address width, stack structure, system call parameters, binary formats, etc. Programs compiled according to some ABI can be executed across OSs that support this ABI.

## Structures

- **Monolithic**: Hard to expand, but fast. Examples: UNIX, Linux.
- **Layered**: An approach to modular systems. Each layer interacts with its immediate neighbors only. Examples: computer networks (TCP/IP).
- **Microkernels**: Non-essential components are implemented as user-level programs, and they communicate via the (smaller) kernel. Easier to extend the OS. Easier to do HW porting. Poorer performance (lots of communication-induced overhead). Examples: Darwin (the base of MacOS / iOS).
![](https://hackmd.io/_uploads/HyciUfb63.png)
- **Modules**: Using **Loadable Kernel Moduels (LKMs)**. The kernel only implements core functions, and new features are loaded dynamically. Examples: Linux, UNIX, Windows, macOS, Solaris.
    - Each kernel section has defined, protected interfaces, like layered systems, but more flexible, as modules can communicate with each other.
    - Kernel has only core functions, like microkernel systems, but more efficient, as module communication does not require message passing.
    - Linux implements this, like dynamically loading necessary drivers when plugging in a USB.
- Most OSs are **hybrid**. Linux is both monolithic and modular.

## MacOS & iOS

![](https://hackmd.io/_uploads/ryFMXnba2.png)

- **User Experience Layer**: user-device interactions *Aqua* (mouse & keyboard) for macOS and *Springboard* (touch) for iOS. 
- **Application Frameworks Layer**: *Cocoa* and *Cocoa Touch* frameworks provide APIs for Obj-C and Swift.
- **Core Frameworks**: Frameworks that support graphics and media, including Quicktime and OpenGL.
- **Kernel Environment**: *Drawin*, including the Mach microkernel and the BSD UNIX Kernel.

Differences between the two:
- MacOS is for Intel arch., while iOS is for ARM-based arch. iOS has some mobile-specific designs: power & memory management, stringent security design.
- Development on iOS is generally more restricted

### Darwin

![](https://hackmd.io/_uploads/ByDDH3-T3.png)

- Darwin provides two system call types: Mach traps and BSD POSIX.
- Mach, BSD, I/O Kit, and **kernel extensions (kexts)** are combined into one address space for performance (message passing occurs, but no copying is needed).

### Android

![](https://hackmd.io/_uploads/rkEQv3Zp2.png)

- Designed by the Open Handset Alliance (led primarily by Google)
- Application development is in Java, but instead of regular Java APIs, Google designed a separate Android API, and compiled to run on the VM **Android RunTime (ART)**.
- Java code → Byte Code (`.class`) → Binary (`.dex`)
- Android adopts **ahead-of-time (AOT)** instead of **just-in-tim (JIT)** compilation. The former improves execution efficiency and power consumption.
- `.dex` files are compiled into native machine codes and installed on a device to be executed by ART.
- Can also write using the **Java Native Interface (JNI)** to bypass the VM and access hardware, but this way limits portability.
- **Hardware Abstraction Layer (HAL)** abstracts physical hardwares, so that developers can write programs that are portable across HW platforms.
- Instead of `glibc`, Google uses the **Bionic** standard C library, designed to have less memory footprint and slower CPUs.

## Booting an Operating System

The general steps are,

- A small **bootstrap program** or **boot loader** llocates the kernel.
- The kernel is loaded into the memory, and it initializes hardware.
- The root file system is mounted.

Oftentimes, BIOS is the boot loader. it then loads a second boot loader in the **boot block** (a fixed disk location). It may be small, and knows only the address on disk and the remainder of the bootstrap program.

Many recent systems use **UEFI (Unified Extensible Firmware Interface)** instead of the BIOS-based boot process,
- It supports 64-bit systems are larger disks better.
- It is a single, complete boot manager, faster than its multi-staged BIOS counterpart.

In the booting process, machine status may be inspected (memory, CPU, attached devices, ...), and some aspects may be initialized (CPU registers, device controllers, memory content, ...).

### Linux

**GRUB** is an open source bootstrap program for Linux and UNIX.

The Linux Kernel image is a compressed file when loaded into memory (to save time and space). The boot loader typically create a temporary RAM File System (`initramfs`) first that contains only necessary drivers and kernel modules. They must be installed to support the real root file system. When this is done, the kernel switches to the real root FS. After all this, Linux creates an initial `systemd` process.

### Android

Despite also being based on Linux, Android uses a different approach. Vendors have to design boot loaders, like **LK (Little Kernel)**.

While Linux discards `initramfs`, Android keeps it as its root FS. After loading the kernel and mounting the root FS, Android starts a `init` process before displaying home screen.

### Special Modes

The boot loader of many OSs allow booting  into **recovery mode** or **single-user mode** to HW issue diagnosis, corrupt file fixing, or even OS reinstalling.

## OS Debugging

### Failure Analysis

- Failed process: **log file** or **core dump**.
- To avoid risks, kernel-level crashes usually dumps memory states to a non-FS section. When rebooting, the booter gathers such information for debugging.

### Performance Monitoring Tuning

- Many **counters** are needed for monitoring, as used in Linux's `top`, for example.
- `/proc`, a psuedo file system, is a kernel memory section that stores per-process / kernel statistics.
- **Tracing tools** collect data for sprcific events, like `strace` (traces system calls of a process), `gdb` debugger, `perf` (Linux performance tools), or `tcpdump` (collects network packets).

### BCC: Dynamic Kernel Tracing

- Debugging interactions between kernel and user is impossible without specifically designed tools.
- **BBC (BPF Compiler Collection)** provides a dynamic, secure, low-impact debugging environment.
- It is a front-end interface of **eBPF (extended Berkeley Packet Filter)** that was origianlly used to filter network traffic.
- Its intructions can be dynamically inserted into running Linux systems, for event capturing or performance monitoring (e.g. disk I/O time).
- **Verifiers** ensure these instructions do not impact performance or security.
- BCC can be used on live production systems without causing harm.

## 雜項

本章結尾有撰寫 Linux Kernel Module，並在 run time 做安裝 / 移除的練習。

- Linux Kernel Module 的撰寫中，有一個 `copy_to_user` 函數，可以把 kernel space buffer 轉至 user space。