TT Lab
Get started
Learn Learning paths Courses

Operating Systems

The Process — Isolation as a Product the OS Sells

Continue in TT Lab

In a nutshell

A process is a product the operating system sells to create the illusion that "this program has a computer of its own", and the core of that illusion is an independent address space.

Why this was needed

To run several programs on one machine, you must guarantee two things. First, a bug in one program must not corrupt the memory of another. Second, a program must not have to care about when it is stopped and when it is resumed.

The abstraction that provides both is the process. Each process has its own virtual address space starting at address 0, and it borrows the CPU for a moment and gives it back without noticing.

How it works

The operating system maintains a PCB (Process Control Block) for each process. Roughly, it holds the following.

A context switch saves the current process's registers into its PCB and restores those of the next process. Moving a few dozen registers is short in itself, but the real cost comes afterward. Once the new process starts running, what the previous process left in the cache and TLB becomes useless, and misses pour in. This indirect cost is much larger than the direct cost.

The way Linux creates processes is also distinctive. fork() duplicates the parent entirely, and exec() overwrites the copy with a new program. Duplicating everything sounds frightening, but it is actually handled with copy-on-write. The parent and child share the same physical pages, and only when one of them tries to write is that page copied. In the common pattern of calling exec() right away, almost no copying happens.

The part of the process state transitions that people often confuse is the zombie. If a child has finished but the parent has not yet collected its exit status with wait(), only the PCB remains and the process becomes a zombie. A zombie uses almost no memory but occupies a process table entry, so if they pile up you cannot create new processes. Conversely, if the parent dies first, the child becomes an orphan and is adopted by init (or the container's process number 1). The incident in which zombies pile up when you start an application as process 1 inside a container comes from this. Process 1 is responsible for reaping orphans, but an ordinary application does not have that code.

What it looks like in the field

In the ps output, a Z in the STAT column means the situation above. The standard response is to add a small init such as tini to the container image or to turn on the runtime's init option. It is also worth knowing the D state (uninterruptible wait), which is usually a wait for disk or network filesystem I/O, and a process in this state does not die immediately even with kill -9.

What to check in the quiz that follows

Check whether you can explain why fork looks expensive but actually finishes cheaply, and where the real cost of a context switch lies.