Programsoskernelresource managerabstractionhardware

What an Operating System Is For

Several programs want the same CPU, memory, disk and network card at the same time; the operating system is the program that owns those resources and hands them out, and everything it does follows from that job.

Conceptual
▶ Interactive
Progress

The problem

Your laptop is running a browser, a database, an editor and a dev server. There is one CPU (a handful of cores), one pool of RAM, one SSD and one network card. None of those programs was written with the others in mind. Who decides which one runs now, whose bytes live at RAM address 0x7f3a0000, and whose packet goes out next?

Four programs, one machine

Hardware is embarrassingly literal. A CPU core executes one instruction stream at a time. RAM is a flat array of bytes with no notion of ownership. An SSD accepts read and write commands for block numbers. A NIC transmits whatever frame you hand it. Nothing in the hardware knows that the browser and the database are different programs, that one should not overwrite the other’s memory, or that a program waiting for a disk read should not burn a core doing nothing.

If every program talked to hardware directly, each would need its own driver for every disk and NIC model, each would have to trust every other program not to scribble on its memory, and one infinite loop would freeze the machine. Early machines actually worked that way: one job at a time, loaded by an operator. The moment you want two programs resident at once, you need a third program whose job is arbitration.

That third program is the operating system. It runs with more privilege than anything else (see User Mode vs Kernel Mode), it is the only code allowed to touch the hardware directly, and every other program gets its CPU time, memory, files and network access by asking it (see System Calls).

The resources, and the abstraction sold for each

For each raw resource the OS invents an abstraction that is easier to program against and safe to hand to untrusted code. A core becomes a process or thread that appears to run continuously. Physical RAM becomes an address space that appears private and contiguous. Blocks on a disk become files with names, sizes and offsets. A NIC becomes a socket you can send() to. A keyboard, a GPU and a USB stick become devices behind a uniform read/write/ioctl interface.

Two things happen at once in every abstraction: it hides mechanism (you never see the SSD’s block numbers) and it enforces policy (you cannot read a file you lack permission for, you cannot exceed your memory limit). The rest of this domain is about what is behind each abstraction and how it fails, because when something breaks in production the abstraction is exactly what stops explaining the symptom.

Where the operating system sits
  1. Applicationsbrowser, database, editor, server — each written as if it owned the machine
  2. Operating systemprocess management · memory management · file system · networking · device management
  3. HardwareCPU cores, RAM, SSD, NIC, GPU, timers, interrupt controller

Kernel versus "the OS" you install

Conceptual

Strictly, the kernel is the privileged program that does the arbitration: Linux, the XNU kernel in macOS, the Windows NT kernel. It runs in a protected CPU mode, it is entered only through system calls and interrupts, and it is the only thing that can program the MMU or a device register. When this domain says "the OS does X" it almost always means the kernel does X.

What you install and call "Ubuntu" or "Windows 11" is a distribution: the kernel plus a C library that wraps system calls (glibc, musl, msvcrt), an init system (systemd, launchd, the Windows Service Control Manager), a shell, package tooling, a window system and a few thousand user-space programs. Those are ordinary processes with no special privilege; ls is a process exactly like your server is. The line that matters for understanding behaviour is user mode versus kernel mode, not "part of the OS" versus "not".

This matters practically. Some behaviour you attribute to "the OS" is really the C library (e.g. malloc deciding whether to use brk or mmap, stdio buffering) or the init system (who reaps orphaned processes). When a symptom does not match the kernel documentation, check which layer you are actually talking to.

What "coordinating" costs

Every abstraction is paid for. Entering the kernel for a system call costs on the order of 100 ns to a microsecond of pure overhead before any work is done. Switching the CPU from one process to another costs roughly 1–5 µs plus the indirect cost of cold caches and a flushed TLB (see Context Switching). Translating every memory access through page tables costs a TLB lookup, and a TLB miss costs a page-table walk of several memory references (see The TLB).

Those costs are why systems engineering is full of batching: reading 64 kB per read() instead of 1 byte, epoll returning many ready sockets per call, io_uring submitting many requests per entry into the kernel, and thread pools that avoid creating a thread per task. Whenever a system is slow with idle CPU, one of the first questions is "how many times per second are we crossing the user/kernel boundary, and could we cross it less?".

Key points

  • Hardware has no notion of programs or ownership; the OS is the program that multiplexes the CPU in time, memory in space, and devices by queueing.
  • For each raw resource the OS sells an abstraction (process, address space, file, socket, device) that hides mechanism and enforces policy.
  • The kernel is the privileged arbiter; a distribution is the kernel plus thousands of unprivileged user-space programs.
  • Applications never touch hardware; they ask via system calls, and the user/kernel boundary is the line that matters.
  • Every abstraction has a cost (syscall entry, context switch, TLB miss), which is why real systems batch.

Why does this exist?

Mechanisms are answers to constraints. Open each question before reading the answer.

Why does an OS exist at all?

Because two programs on one machine need an arbiter for the CPU, memory and devices, and neither program can be that arbiter without trusting the other. The arbiter must run with more privilege than either, which is what a kernel is.

Why not let programs talk to the disk directly?

Every program would need drivers for every device, and one buggy program could corrupt any file. Routing device access through the kernel gives one driver per device and one place to check permissions.

Why distinguish kernel from distribution?

Because behaviour you debug — malloc policy, process reaping, stdio buffering — is often decided by user-space components, not the kernel, and you have to know which documentation to read.

The OS as a resource manager

The OS as a resource manager
Every program wants the same four pieces of hardware. The kernel sits between them and arbitrates.
↓ system calls ↓
Operating system (kernel)
Process mgmt
Memory mgmt
File system
Networking
Device mgmt
↓ drivers, MMU, interrupts ↓
CPU1 app
RAM1 app
Disk1 app
NIC1 app
Browser: One process per tab, a lot of heap, sockets for every page, a disk cache, and the GPU/display for painting.
Click an app to see what it uses right now.

How it fails

What the failure looks like from inside real software.

  • A runaway process at 100% CPU does not freeze the machine, because the scheduler preempts it — but it does steal a core; see The OS Debugging Playbook: Four Symptoms, Fourteen Causes.
  • A program with a wild pointer crashes with SIGSEGV instead of corrupting another process, because the address space abstraction refuses the access.
  • A process opens sockets without closing them and hits EMFILE (too many open files): the descriptor abstraction has a per-process limit the program never knew about.
  • Blaming "the OS" for slow small writes when the C library’s stdio buffer or the file system’s journaling is the actual cause.