Processes — Concept, Scheduling, Operations & IPC
Press Next → or use ← → arrow keys
What Is a Process? The Program Comes Alive
A program is the recipe (a file on disk). A process is the cook — a program in execution, with its own program counter, registers, stack and heap. The same recipe can bake ten cakes in ten kitchens: one program, many processes.
A program is a passive file of instructions. A process is that program in execution — an active entity the OS can pause and resume at the exact instruction it stopped on.
The Memory Layout of a Process
Text and data are fixed at load time. The heap grows one way and the stack the other, into the free space between them. If they ever collide, you get the classic stack overflow.
The Five Process States
A process is admitted (New→Ready), dispatched (Ready→Running), and either times out (Running→Ready), blocks on I/O (Running→Waiting) or exits. A waiting process cannot jump straight to Running — it must pass back through Ready first. Only one process runs per core.
The Process Control Block (PCB)
For every process the kernel keeps one struct — its identity card. Linux calls it task_struct; Windows calls it EPROCESS. On a context switch, everything needed to resume the process is saved here.
| Field | What it holds |
|---|---|
| PID | Process ID (plus PPID, UID, GID) |
| State | New / Ready / Running / Waiting / Terminated |
| Program Counter | Address of the next instruction to run |
| Registers | RAX, RBX, RSP, RBP, flags — saved every switch |
| Memory info | Base/limit registers, page-table pointer |
| I/O status | Open file descriptors, devices, pending I/O |
| Accounting | CPU time, priority, scheduling parameters |
On Linux, ps -ef lists every process's PID, PPID, state and CPU time, and
cat /proc/<pid>/status shows a live snapshot of that task's task_struct
through the /proc pseudo-filesystem.
Process Scheduling — The Queues
The short-term scheduler dispatches a ready process to the CPU. When its time slice expires it returns to the ready queue; when it needs I/O it moves to a device queue and, once the I/O completes, rejoins the ready queue. Scheduling is what makes multiprogramming work.
The Three Schedulers
CPU-bound processes (matrix multiply, video encode) run long bursts with little I/O; I/O-bound ones (editors, web servers) make short bursts between long waits. A good scheduler mixes both — all-CPU leaves the disk idle, all-I/O leaves the CPU idle.
Anatomy of a Context Switch
Operations on Processes — fork & exec
| Aspect | fork() alone | fork() + exec() |
|---|---|---|
| Child's code | same as parent | a brand-new program |
| PID | new (e.g. 4822) | new (e.g. 4822) |
| Result | two identical processes | parent + a different program |
The Process Tree
Every process except init (PID 1) has exactly one parent, so processes form a
tree. Run pstree to see yours. Kill a parent and its children usually
become orphans — adopted and reaped by init.
How Processes End
| Term | What happened | The fix |
|---|---|---|
| 🧟 Zombie | Child exited but the parent never called wait() | Parent must wait() or handle SIGCHLD |
| 👶 Orphan | Parent died before the child | init adopts & reaps it automatically |
| 😈 Daemon | Deliberately orphaned to run in the background | Intentional — fork twice, become session leader |
exit(0) or returning from main() — signals success to the parent.exit(non-zero) — the parent inspects the code with WEXITSTATUS.kill -9 (SIGKILL) — which cannot be caught.Inter-Process Communication (IPC)
That is exactly IPC. Processes are isolated by design — one cannot read another's memory. The shared door is shared memory; the phone is message passing.
Four reasons: information sharing (many users, one file), speedup (parallel workers), modularity (small trusted services), and convenience (editing, compiling and printing at once).
Shared Memory vs Message Passing
| Aspect | Shared Memory | Message Passing |
|---|---|---|
| Speed | Very fast — direct access | Slower — kernel copy each message |
| Setup | High — mmap, permissions | Low — send() / recv() |
| Sync | Manual — semaphores/mutexes | Built-in (send/receive blocks) |
| Best for | Large data, one machine | Small messages, distributed |
Producer–Consumer — The Classic Problem
in points to the next free slot, out to the next full one; one slot is always left unused so "full" ≠ "empty".
With busy-wait loops on a real multiprocessor, reads and writes to in and out
can interleave and corrupt data — a race condition. The fix is
semaphores (covered in the synchronisation chapter). Never ship unguarded shared memory.
The IPC Toolbox
| does in the shell. Named pipes (FIFOs) persist on the filesystem.msgsnd()/msgrcv(). Persist beyond the sender, support priorities.Blocking vs Non-Blocking · IPC in the Wild
| Call | Synchronous (blocking) | Asynchronous (non-blocking) |
|---|---|---|
send() | Blocks until the message is received | Returns immediately (queued) |
recv() | Blocks until a message arrives | Returns at once with data or "would block" |
| Style | Simple — the caller waits | Concurrent — the caller polls or is notified |
cat log | grep ERROR | wc -l — three processes, two pipes, each stage's stdout wired to the next stage's stdin.Common Pitfalls
| Pitfall | Symptom | Fix |
|---|---|---|
| Zombie explosion | Process table fills with defunct entries | Parent wait()s or handles SIGCHLD |
| Fork bomb | System freezes — recursive fork() | Set ulimit -u; never fork unbounded |
| Shared-memory race | Data corruption, random crashes | Guard with semaphores or mutexes |
| Deadlock in send() | Both processes wait forever | Non-blocking sends or timeouts |
| Pipe with no reader | Writer gets SIGPIPE and dies | Handle SIGPIPE or check write() |
| Lost signals | A signal fires while one is pending | Signals aren't queued — use signalfd / MQs |
Eight Ideas Worth Remembering
fork() returns twice — 0 in the child, the child's PID in the parent. Always check the <0 error case first.wait() for every child or reap them via a SIGCHLD handler.From One Process to Thousands Cooperating
From a program coming alive, through its states, its PCB, the scheduler's queues and context switches, how it forks and dies, all the way to how isolated processes cooperate through IPC — you now have the full life story of a process.
Dive into CPU scheduling algorithms (Round Robin, priority, CFS) and
process synchronisation (semaphores, mutexes, the critical-section problem). Try
ps -ef, pstree and strace to watch real processes at work.
🔄 End of tutorial · Press ← to review, or click Restart