Skip to content
Published on

[OS Concepts] 02. Operating System Structures and Services

Authors

Operating System Services

An operating system provides various services to users and programmers. These services can be broadly divided into two categories.

Services for Users

1. User Interface (UI)

  • CLI (Command-Line Interface): Text-based command input. Shells like bash, zsh
  • GUI (Graphical User Interface): Mouse and icon-based interface. Windows, macOS
  • Touchscreen Interface: Gesture-based interaction on mobile devices

2. Program Execution

The system must be able to load programs into memory and run them. Programs can terminate normally or abnormally (with an error indication).

3. I/O Operations

A running program may request I/O. For security and efficiency, user programs cannot directly control I/O devices; the OS provides I/O facilities.

4. File System Manipulation

Performs reading, writing, creating, deleting, searching, and permission management for files and directories.

5. Communication

Information exchange between processes is needed. There are two models.

  • Shared Memory: Multiple processes share a memory region
  • Message Passing: Processes exchange messages through the OS

6. Error Detection

Continuously monitors for errors in the CPU, memory, I/O devices, and user programs.

Services for System Efficiency

  • Resource Allocation: Appropriately distributes resources when multiple processes run concurrently
  • Logging: Records which programs use which resources and how much
  • Protection and Security: Prevents interference between processes in multi-user environments and controls external access

System Calls

A system call is a programming interface to the services provided by the OS. It is used when user programs request kernel functionality.

System Call Processing Flow

[System Call Operation Flow]

User Program           C Library           Kernel
     |                    |                  |
     |-- open() call ---->|                  |
     |                    |-- Set system     |
     |                    |   call number    |
     |                    |   in register    |
     |                    |                  |
     |                    |-- trap instr --->|
     |                    |   (mode switch)   |
     |                    |                  |-- Look up handler
     |                    |                  |   in syscall table
     |                    |                  |
     |                    |                  |-- Execute sys_open()
     |                    |                  |
     |                    |<-- Return result -|
     |<-- Return fd ------|   (mode restore)  |
     |                    |                  |

System Call API

Programmers usually do not call system calls directly but use them through APIs (Application Programming Interfaces).

  • POSIX API: Used on Unix, Linux, macOS
  • Windows API: Used on Windows systems
  • Java API: JVM translates to underlying OS system calls
// File copy example using POSIX API
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#define BUF_SIZE 4096

int main(int argc, char *argv[]) {
    int src_fd, dst_fd;
    ssize_t bytes_read;
    char buffer[BUF_SIZE];

    // open() - file system related system call
    src_fd = open(argv[1], O_RDONLY);
    if (src_fd == -1) {
        perror("Failed to open source file");
        exit(EXIT_FAILURE);
    }

    dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dst_fd == -1) {
        perror("Failed to create destination file");
        exit(EXIT_FAILURE);
    }

    // read(), write() - I/O related system calls
    while ((bytes_read = read(src_fd, buffer, BUF_SIZE)) > 0) {
        if (write(dst_fd, buffer, bytes_read) != bytes_read) {
            perror("Write failed");
            exit(EXIT_FAILURE);
        }
    }

    // close() - file descriptor release system call
    close(src_fd);
    close(dst_fd);

    return 0;
}

Types of System Calls

CategoryExamples (POSIX)Description
Process Controlfork(), exec(), wait(), exit()Process creation, execution, termination
File Managementopen(), read(), write(), close()File open, read, write, close
Device Managementioctl(), read(), write()Device request, release, read/write
Information Maintenancegetpid(), alarm(), time()Time, date, process information
Communicationpipe(), shmget(), mmap()Pipes, shared memory, memory map
Protectionchmod(), chown(), umask()Permission setting, owner change

System Call Parameter Passing Methods

There are three methods for passing parameters to system calls.

  1. Registers: Pass parameters directly in CPU registers (fastest but limited by register count)
  2. Memory Block: Store parameters in a memory block and pass the block address via register
  3. Stack: Program pushes parameters onto the stack, and the OS pops them

Operating System Structures

Monolithic Structure

The simplest structure where all kernel functions run in a single address space.

[Monolithic Kernel]

+------------------------------------------+
|           User Programs                   |
+------------------------------------------+
|          System Call Interface            |
+------------------------------------------+
|                                          |
|  File System | Process Mgmt | Memory Mgmt|
|  Networking  | Device Drivers | I/O Mgmt |
|                                          |
|     All running in kernel space           |
+------------------------------------------+
|               Hardware                    |
+------------------------------------------+

Example: Traditional UNIX, Linux
  • Pros: Good performance with low system call overhead
  • Cons: Difficult to implement and maintain; one bug affects the entire system

Layered Structure

Divides the OS into multiple layers, where each layer uses only the functions of the layer directly below it.

[Layered Structure]

+-------------------+
| Layer N: User UI  |
+-------------------+
| Layer N-1         |
+-------------------+
|       ...         |
+-------------------+
| Layer 1: Mem Mgmt |
+-------------------+
| Layer 0: Hardware |
+-------------------+

Each layer can only call the layer below it
  • Pros: Easy to implement and debug
  • Cons: Overhead from inter-layer calls; difficult to define layers

Microkernel

Keeps only minimal functionality in the kernel and moves the rest to user space.

[Microkernel Structure]

User space:
+--------+ +----------+ +---------+ +--------+
|File    | |Device    | |Network  | |Memory  |
|Server  | |Drivers   | |Server   | |Server  |
+--------+ +----------+ +---------+ +--------+
     |          |            |          |
+------------------------------------------+
| Microkernel: IPC + Basic Scheduling + Mem |
+------------------------------------------+
|               Hardware                    |
+------------------------------------------+

Example: Mach, QNX, MINIX 3
  • Pros: Good extensibility, easy to port, high reliability
  • Cons: Message passing overhead between user space and kernel space

Hybrid Structure

Most modern OSes use a hybrid approach combining multiple structures.

  • Linux: Basically monolithic but supports loadable kernel modules (LKM)
  • Windows: Influenced by microkernel design but includes many functions in the kernel for performance
  • macOS: Mach microkernel + BSD UNIX kernel = XNU hybrid kernel
[macOS/iOS XNU Kernel]

+------------------------------------------+
|      User Experience Layer (Aqua/Cocoa)   |
+------------------------------------------+
|      Application Framework (Core Foundation)|
+------------------------------------------+
|              Kernel Environment            |
|  +--------+  +--------+  +---------+     |
|  | Mach   |  | BSD    |  | I/O Kit |     |
|  | (IPC,  |  | (POSIX |  | (Driv-  |     |
|  | Threads|  |  API,  |  |  ers)   |     |
|  | VM)    |  | Network|  |         |     |
|  +--------+  +--------+  +---------+     |
+------------------------------------------+
|               Hardware                    |
+------------------------------------------+

Loadable Kernel Modules (LKM)

The Linux kernel can dynamically load/unload modules.

// Linux kernel module example (hello.c)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example");
MODULE_DESCRIPTION("Hello World Kernel Module");

// Called when module is loaded
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, Kernel World!\n");
    return 0;
}

// Called when module is unloaded
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, Kernel World!\n");
}

module_init(hello_init);
module_exit(hello_exit);
# Kernel module management commands
sudo insmod hello.ko    # Load module
lsmod                   # List loaded modules
sudo rmmod hello        # Unload module
modinfo hello.ko        # Module information

System Boot

When a computer is powered on, the OS starts through the following process.

[Boot Process]

1. Power ON
      |
      v
2. BIOS/UEFI execution (Firmware)
   - POST (Power-On Self Test)
   - Hardware initialization
      |
      v
3. Boot loader execution (GRUB, etc.)
   - Load from MBR/GPT on boot disk
   - Select kernel image
      |
      v
4. Kernel load and initialization
   - Hardware detection
   - Driver initialization
   - Mount root file system
      |
      v
5. init/systemd execution (PID 1)
   - Start system services
   - Provide login prompt

GRUB Boot Loader

GRUB (GRand Unified Bootloader) is the most widely used boot loader in Linux.

# GRUB configuration file example (excerpt from /boot/grub/grub.cfg)
menuentry 'Ubuntu' {
    set root='(hd0,gpt2)'
    linux /vmlinuz root=/dev/sda2 ro quiet splash
    initrd /initrd.img
}

menuentry 'Ubuntu (Recovery Mode)' {
    set root='(hd0,gpt2)'
    linux /vmlinuz root=/dev/sda2 ro recovery nomodeset
    initrd /initrd.img
}

On UEFI-based systems, the UEFI firmware finds and executes the boot loader from the ESP (EFI System Partition). UEFI provides Secure Boot functionality to restrict execution to signed boot loaders only.


Summary

An operating system provides various services, and user programs access kernel functions through system calls. OS structures range from monolithic to microkernel, and modern OSes adopt a hybrid approach pursuing both performance and flexibility. During the boot process, firmware, boot loader, and kernel sequentially transfer control to initialize the system.