Operating System
Virtualization vs Abstraction (and Why VMs Aren't Containers)
I open every OS course with one question before touching a diagram: why does an operating system need to exist at all? Without one, every program would need to know exactly where in physical RAM it runs, and no two programs could safely share one CPU. The OS's job is maintaining an illusion — that your process owns the CPU, owns a clean memory space, owns its own disk — while actually managing a resource shared across dozens of processes doing the same thing.
Abstraction and virtualization are not the same thing
- Abstraction hides complexity. A file descriptor is an abstraction over the mess of disk blocks, sectors, and controllers underneath.
- Virtualization shares resources. It creates the illusion that you have exclusive access to something you're actually sharing with other processes.
They're related — virtualization is built using abstractions — but distinct. Shorthand: abstraction = complexity, virtualization = resources.
| Physical Hardware | What hardware actually provides | OS Abstraction | What the programmer sees |
|---|---|---|---|
| CPU | Executes instructions on a limited number of cores | Process / Thread | main(), threads, processes |
| RAM | Physical memory addresses | Virtual Memory | Variables, pointers, malloc() |
| SSD / HDD | Blocks, sectors, physical storage | File / Directory | open(), read(), write() |
| Network Card | Ethernet/IP packets | Socket | socket(), send(), recv() |
Every row is the same move: the OS takes something physical and messy, hands the programmer something clean and logical instead.
Where this gets tested: VM vs container
The question that actually separates understanding from memorized "containers are lighter than VMs": what, specifically, is being virtualized in each case?
A virtual machine virtualizes the entire machine — a hypervisor virtualizes hardware, and each VM runs its own full guest OS on top. A container doesn't virtualize hardware at all; it isolates a process's view of an already-running OS, and every container shares the host's kernel.
VM = virtualization, container = isolation. Calling containers "lightweight VMs" gets the mechanism backwards — it's the single most common mistake I see in interviews.
flowchart TB
subgraph VM["Virtual Machines"]
direction TB
VA["App 1 | App 2 | App 3"] --> VB["Bins/Libs (x3)"]
VB --> VC["Guest OS (x3)"]
VC --> VD["Hypervisor"]
VD --> VE["Host OS"]
VE --> VF["Infrastructure"]
end
subgraph CT["Containers"]
direction TB
CA["App 1 | App 2 | App 3"] --> CB["Bins/Libs (x3)"]
CB --> CC["Container Engine"]
CC --> CD["Operating System"]
CD --> CE["Infrastructure"]
end
Three guest OS copies vs. zero — that's where the weight difference comes from, not a vague "containers are more efficient."
How containers isolate without a hypervisor
Namespaces. One of the few OS concepts you can inspect directly on a running system:
$ lsns
NS TYPE NPROCS PID USER COMMAND
... mnt 21 117 vscode /bin/sh
... uts 21 117 vscode /bin/sh
... ipc 21 117 vscode /bin/sh
... pid 21 117 vscode /bin/sh
... net 21 117 vscode /bin/shEach namespace type hides a different category of resource — PID namespace hides other processes' PIDs, net namespace hides other containers' network interfaces. A container is, mechanically, a regular process on the host OS given a restricted namespace view. Docker's "magic" is namespaces + cgroups + capabilities wired together — cgroups cap what resources a process can use, namespaces control what it can see.
One more distinction worth being exact about: userspace is where ordinary programs (shell, app, libc) run, as opposed to the kernel. Namespaces control visibility; userspace is about protecting the kernel from a crashing app — different problems.
Quick recall
- OS exists to maintain an illusion: exclusive CPU, clean memory, private disk — over resources actually shared across processes
- Abstraction hides complexity; virtualization shares resources — related but not the same thing
- VM = virtualization (own guest OS, hypervisor); container = isolation (shares host kernel, uses namespaces)
- Namespaces control what a process can see; userspace is where it executes — different problems
I don't move to processes or scheduling until this is solid — "why does a container start in milliseconds" and "why can a container see host CPU count" both fall out of it directly once abstraction-vs-virtualization and VM-vs-container are genuinely distinct in your head.
Quick quiz
1. What's the one-line distinction between abstraction and virtualization?
2. What's the actual mechanism difference between a VM and a container?
3. What do Linux namespaces actually control?