A modular operating system simulator in C/C++ that runs the core of an OS in miniature: scheduling, virtual memory, synchronisation, IPC and a file system.
Edit the processes, pick an algorithm and press Run. The CPU, ready queue and Gantt chart update tick by tick. Drag the slider to jump to any moment, or step forwards and back. Lower priority numbers run first.
Jump back to any moment of the live runner's schedule, change one scheduling decision, and watch the timeline fork. It uses the processes, algorithm and quantum currently set in the live runner above.
Every process gets its own note, played while it holds the CPU. Choose two algorithms to hear them side by side: the first in your left ear, the second in your right. Headphones work best. It plays the processes from the live runner.
A soft tick marks each context switch. Round Robin sounds busy because it switches often, while FCFS plays long steady notes.
You are the CPU scheduler. Choose which ready process runs next and try to beat the algorithms on average waiting time. Shortest-remaining-time-first is provably optimal for this measure, so the hint shows its choice.
You are the virtual-memory manager. Hits and empty frames are handled for you. When a page fault finds every frame full, you choose which page to evict. Fewer faults is better. The future is hidden unless you choose to peek, and the hint shows what the optimal policy would evict.
Something is broken. Reproduce the bug, then choose a fix. Every outcome comes from running a simulation, so a plausible-sounding fix can still fail.
A system is misbehaving. Read the monitor output, then name the bug. Each case is generated by running a real simulation, so the numbers change every time. Wrong answers are worth learning from: some of these look alike.
A tiny operating system you can drive from a command line. Spawn processes, switch schedulers, advance the CPU, kill things and touch memory pages. Type help, press Tab to complete, or tap a command below.
Two threads each run counter++, which is really three steps: load, add, store. Those six steps can interleave in exactly 20 ways. Build one yourself, or click any of the 20 to replay it.
Average waiting, turnaround and response time for the same four processes under each algorithm (lower is better).
Each axis is scaled against the best algorithm for that measure, so a full-size corner means it won.
A small quantum answers quickly but switches constantly. A large one behaves like FCFS. This sweeps the quantum from 1 to 10 for the processes in the demo at the top (use Randomise processes there to try other workloads).
Process creation, process-control blocks and the full state-transition cycle.
FCFS, SJF, Priority, Round Robin and Multilevel Feedback Queue, with Gantt traces and comparisons of waiting, turnaround and response time, throughput and CPU utilisation.
Paging, page-table address translation, page-fault handling, and FIFO, LRU and Optimal replacement with fault-rate and utilisation analysis.
Threads, mutexes and semaphores. Race conditions, critical sections, deadlock scenarios and shared-resource coordination.
Pipes, shared memory and message queues for exchanging data between isolated processes.
File creation, reads and writes, directory structures, file allocation and controlled access to storage.
A virtual address splits into a page number and an offset. The page table maps the page to a physical frame.
Two threads each add 1 to a shared counter 1,000 times, so the correct total is 2,000. Without a mutex, updates overwrite each other.
The Banker's algorithm checks whether the system can still finish every process in some order. Pick the free resources to see the result.
Circles are processes, squares are resources. Solid arrows show who holds a resource, dashed arrows show who is waiting. A cycle means no process can ever continue.
The same sequence on a 32-block disk: create A (5 blocks), B (3), C (8), D (4), E (6), delete B and D, then create F (8).
| Mechanism | Data path | Synchronisation | Best for |
|---|---|---|---|
| Pipe | Copied through a kernel buffer | Built in: reads block until data arrives | Streaming between related processes |
| Message queue | Copied through a kernel queue | Built in, with typed messages | Discrete messages between unrelated processes |
| Shared memory | No copy, both processes map the same pages | You provide it (semaphores or mutexes) | Large, frequent data exchange |
Every access checks the TLB first. On a miss, a second memory access reads the page table. The dashed line marks your chosen hit ratio.
A producer adds items to a bounded buffer and a consumer removes them. Semaphores make the producer wait when the buffer is full and the consumer wait when it is empty.
If each process spends a fraction p of its time waiting for I/O, n processes in memory keep the CPU busy about 1 − pn of the time. More processes hide more I/O wait, with diminishing returns.
Five philosophers share five forks and need two to eat. If everyone grabs the left fork first, they can all end up waiting forever. Picking the lower-numbered fork first breaks the cycle.
Free blocks of 100, 500, 200, 300 and 600 KB receive four requests: 212, 417, 112 and 426 KB. Where each request lands depends on the strategy.
Small pages waste little inside the last page but need a large page table. Large pages do the opposite. The best size sits where the two costs meet, near the square root of 2 × process size × entry size.
Typical access times, on a log scale. These are rough orders of magnitude, not measurements of any one machine. They explain why paging and caching matter.
If an L1 cache hit took 1 second, a hard-disk access would take about 4 months.
One workload can favour any algorithm. This runs all five on the same batch of random workloads (4 to 5 processes each) and compares the results.
Ties count as a win for every tied algorithm, so the last column can add up to more than 100%.
The order in which a disk head services requests changes how far it travels. Enter cylinder requests (0 to 199) and a starting position.
SCAN sweeps toward cylinder 0 first, then reverses. C-SCAN sweeps upward, jumps back to 0 and continues.
The serial part of a program limits what extra cores can do. A program that is 95% parallel never gets past 20 times faster, however many cores you add.
With 32-bit addresses, 4 KB pages and 4-byte entries, a flat page table always costs 4 MB. A two-level table only allocates the second-level tables a process actually uses.
Assumes the mapped memory is contiguous. Two-level tables win until nearly the whole address space is in use.
Excerpts and output from the C/C++ implementation.
C and C++, POSIX threads, Linux system calls, shell scripting and process-level resource monitoring on Linux. Companion tools: a Streamlit app and a Colab notebook.