Operating Systems · Module 2 — Processes & Threads
Creating processes: fork, exec, wait; zombies and orphans
The kernel makes a near-identical copy of the calling process. The copy is the child; the original is the parent.
Sign in to track your score
Aisha clicks "Build" in her editor. A moment later the compile job exists as PID 2317.
The editor is an ordinary user-mode program. It cannot create memory or claim a core — Module 1 established that.
So the editor had to ask the kernel. And the way it asks is genuinely strange: it does not say "start gcc". It says "make a copy of me".
Why & what
Process creation on Unix-like systems is two separate steps.
fork() — one process becomes two. The kernel makes a near-identical copy of the calling process. The copy is the child; the original is the parent.
The child gets a copy of the parent's memory, a copy of its open files, and a brand new PID. Both then continue from the very next line of code — the same line, in two processes.
How does each one know which it is? fork() returns a different value in each: 0 in the child, and the child's PID in the parent. That single difference is how the code branches.
exec() — the child changes what it is. The child throws away all the copied memory and loads a different program in its place. Same PID, completely different code, data, heap and stack.
wait() — the parent pauses for the child. The parent moves to Waiting until the child finishes, then reads the child's exit code.
Why two steps and not one? Because the gap between fork and exec is useful. In that gap the child is still a copy of the parent, and it can adjust things before becoming the new program most commonly, redirecting where its output goes. That is exactly how a shell implements gcc matrix.c > build.log.
How it works
- The editor calls fork(). Now there are two processes: PID 2210 and a new child. Both are running the editor's code.
- They branch on the return value. The child sees 0. The parent sees the child's PID.
- The child calls exec("gcc"). Its copied memory is wiped and gcc is loaded in. It is now the compile job, PID 2317.
- The parent calls wait(). The editor goes to Waiting and stops using the CPU until the compile finishes.
- The compiler exits. It becomes Terminated. The editor wakes, reads the exit code — 0 for success — and the OS deletes the last of PID 2317.

Common confusion
"Threads make everything faster." Only if the work can genuinely happen at the same time. A thread that spends its life waiting on the network frees a core for others — a clear win. But splitting one calculation across four threads that constantly wait for each other can be slower than one thread, because of the coordination cost Module 4 introduces.
"Each thread has its own heap." No. This is the single most important line in the module.
Threads have their own stack and share the heap. Local variables inside a function are private; anything allocated on the heap is visible to all of them.
"Concurrency and parallelism are the same word." They are not, and this is a favourite interview trap.
- Concurrency — several tasks are in progress at once. They may be taking turns on one core.
- Parallelism — several tasks are genuinely executing at the same instant, on different cores.
On a single-core machine you can have concurrency but never parallelism. The Nova-14 has 4 cores, so the browser's four threads can be truly parallel — but 200 background programs on 4 cores are only ever concurrent.
"Modern browsers use one process per tab, so threads must be bad." They use both.
Separate processes per tab so one crashed tab does not kill the browser; multiple threads inside each tab because they need to share page data cheaply. The choice is about isolation versus sharing, not about which is better.
Interview angle
"Difference between a process and a thread?" Answer with the split, not a list of adjectives: threads share code, data, heap and open files, and keep a private stack, registers and program counter. Then give one consequence: switching threads is cheaper because the memory map does not change.
"When would you use threads over processes?" When the parts need to share a lot of data and you accept that one bad thread takes the rest down. When you need isolation, pay for separate processes.
The follow-up that trips people is "what is the danger of the shared heap?" Say the words race condition and explain it in one line: two threads writing the same variable at the same time can leave it holding a wrong value, silently. That is the sentence Module 4 opens on.
- 1.
Why is switching between two threads of the same process cheaper than switching between two processes?