Prerequisites from CS1:

Operating Systems Overview

An operating system must handle:

  • Loading programs into memory
  • Scheduling / starting and stopping processes
  • Managing memory use
  • Managing I/O devices
  • Managing who is allowed to execute programs
  • How a privileged human can configure, control and debug the system

A good operating system will optimise for:

  • Efficiency: minimal overhead; maximal hardware usage
  • Fairness: shares out system resources according to policy
  • Reliability: keeps working even when programs are buggy / hardware is faulty
  • Security: keeps working even when users / programs are adversarial
  • Usability: offers services and behaviours that help humans get things done
  • Abstraction: offers high-level, general and powerful services
  • Simplicity: consists of a small codebase that is maintainable and comprehensible

The operating system ‘shares out the hardware’ to user processes. Sometimes referred to as ‘secure multiplexing of computer resources’.

Most real OSes are ‘multi-user’ meaning they distinguish multiple user identities. In this case, it is usually the case that each process ‘belongs’ to one user.

Virtualisation

The operating system provides a ‘virtual computer’ for programs to run in, i.e.:

  • virtual CPU = thread(s) of execution
  • virtual memory = private address space
  • virtual storage = files on disk
  • virtual network = sockets

Operating systems do not only virtualise hardware however programs that only do this are called a virtual machine monitor or hypervisor.

Operating systems also handle:

  • Communication: interaction between programs
  • Abstraction: higher-level abstractions of things like sectors on a disk, i.e. files
  • Control and inspection: services that control running programs; inspecting / debugging

Concurrency

Modern operating systems expose concurrent abstractions to their users:

  • user(s) may create multiple processes that exist simultaneously
  • process may contain multiple threads
  • processes / threads may share resources (memory, files, ..)

While two programs (on one core) are not actually running at the same time, they do not control when the switching happens and how their interactions are ordered. Concurrency refers to the uncontrolled interaction of processes.

To notify the operating system that a device has finished, a hardware interrupt is sent to the CPU causing it to jump to a special routine. This also means the operating system itself is a concurrent program; the CPU interrupt saves and restores a context. There are also special devices like timers which allow an OS to switch to another activity (this is how preemptive schedulers work).

Core Concepts

  • Address Space

    Address space: memory consists of a collection of locations that are somehow numbered

    Link to original
  • Loading a program: make a running process given a static program
  • User vs system: processes either run in ‘user’ or ‘system’ (“kernel mode”; ring 0) The execution cycle of a kernel looks something like this: When introducing separate rings, it looks more like this: When running in user mode, the CPU prohibits certain instructions that could violate security of multiplexing, e.g. by accessing devices and memory they shouldn’t. To jump to kernel mode, we use a software interrupt instructions (system call).
  • Limited Direct Exceution

    Limited direct execution: programs run on the real hardware but the OS can regain control

    For the OS to run a user program on real hardware, we need to:

    1. Put the CPU into user mode
    2. Jump to the user program code in memory
    3. Ensure that it eventually somehow jumps back to the OS

    For example, on Intel CPUs, the iret instruction performs the first two. The third one depends on our scheduler:

    • A preemptive scheduler would use a timer interrupt that fires periodically
    • A cooperative scheduler would rely on the program doing I/O or yielding

    Any interrupt will put the CPU into kernel mode and jump into the OS:

    • Timer interrupt: hardware interrupt raised by programmable timer
    • Doing I/O or yielding: software interrupt / system call
    Link to original
  • System Call

    System calls occur when programs need to use the OS for its privilege or abstractions it makes a call analogous to a procedure call. We need a special CPU instruction to do this. The caller identifies the target code by a small number and not its address.

    Link to original
    For example, JnS stores the current PC value in the first address of the routine we are jumping to, then continuing with the instruction following that (in modern machines, we just push the address to the stack). To return from the subroutine, we JumpI back to the subroutine name. In the case of system calls, it may be something like syscall 42 or int 42 which would call the 42nd procedure. Some examples of these are ReadFile, WriteFile, OpenFile, CloseFile, GetPid, Connect, Listen, Fork, Exec.