What an Operating System Does

You write applications that run on top of an operating system every day, and mostly you can ignore it — until a performance mystery, a concurrency bug, or a resource limit forces you to understand what's underneath. The OS is doing two jobs for you constantly: managing the hardware's finite resources, and giving you clean abstractions over messy reality. Understanding those two jobs is understanding the machine your code actually runs on.

Most application and backend engineers treat the operating system as an invisible layer — and mostly can, until something goes wrong at a level their framework doesn’t explain. This series covers OS concepts for engineers who build on top of it — not to write an OS, but to understand the machine your code runs on, so you can reason about performance, concurrency, and resources. This first post covers the OS’s two fundamental jobs (resource management and abstraction) and the user/kernel boundary that structures everything. It’s the foundation the rest builds on.

The two jobs of an OS

An operating system does two fundamental things, and almost everything it provides serves one of them:

Your programs
     │  (use clean abstractions: files, processes, sockets, virtual memory)
┌────▼─────────────────────────────────────┐
│ Operating System                          │
│  - manages resources (CPU, memory, I/O)   │  referee + abstraction layer
│  - provides abstractions over hardware    │
└────┬─────────────────────────────────────┘
     │
  Hardware (CPU, RAM, disk, network, devices)

These two jobs — manage the finite hardware, and abstract its messiness — are the lens for the whole series. Processes and threads (abstractions over “a running program”) plus scheduling (managing the CPU); virtual memory (abstraction over physical RAM) plus memory management (managing it); files and I/O (abstraction over storage/devices). Every OS concept is either an abstraction it provides or a resource it manages, usually both. Hold that framing and OS concepts stop being a disconnected list.

Kernel mode and user mode

The OS’s ability to manage and protect resources rests on a hardware feature: two privilege levels, kernel mode and user mode:

This split is why the OS can protect and manage resources: applications can’t directly touch hardware or each other’s memory (that would break isolation and safety), so they must go through the OS for anything privileged. A buggy or malicious program in user mode can’t crash the machine or read another program’s memory, because the hardware forbids it — only the trusted kernel has that power. This is the foundation of OS protection: untrusted applications run restricted (user mode), and only the trusted kernel runs privileged (kernel mode). It’s the same isolation principle you saw in containers (which use kernel features to isolate processes) and it’s enforced by the CPU itself.

System calls: the boundary

If applications run restricted in user mode but need to do privileged things (read a file, send network data, create a process), how? Through system calls (syscalls) — the controlled interface by which user-mode programs request services from the kernel:

User program: read(fd, buf, n)
   → syscall → CPU switches to kernel mode → kernel reads from the device → 
   → returns data + control back to user mode

System calls are the interface between your applications and the OS — everything your program does that touches the outside world (files, network, processes, memory, time) ultimately goes through syscalls. They’re the boundary between the abstraction layer you use and the resource management/hardware access the kernel controls. Understanding that “my program does X” often means “my program makes a syscall to ask the kernel to do X” is key: it explains where the cost of I/O comes from (crossing the boundary), why some operations are expensive, and how tools like strace (which shows a program’s syscalls) let you see what a program is really doing. The syscall boundary is where your code meets the OS.

Why this matters for engineers

You don’t write operating systems, so why learn this? Because the OS’s behavior leaks into your applications, and understanding it makes you a better engineer at diagnosing and designing:

The goal of this series is exactly that: not to make you an OS developer, but to give you the mental model of the machine your code runs on, so the OS stops being an invisible mystery and becomes something you can reason about when it matters. The next post starts with the OS’s central abstraction for “a running program”: the process.

Key takeaways

Further reading

Sources & References