Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OS Simulator — Process, Memory & I/O Management in C++

A simulated operating system kernel built in C++ using object oriented priciples , modeling how a real OS schedules processes, manages memory through paging, and arbitrates access to I/O devices — implemented as a clean, extensible class hierarchy rather than a single procedural main().

                        Kernel
             /             |             \
    ProcessManager   MemoryManager     IOManager
          |                |                |
      Scheduler          Pager        DeviceManager
          |
  FCFS  SJF  RR  Priority  MLFQ

Build & Run

g++ -std=c++17 -Iinclude -Wall src/*.cpp main.cpp -o os_simulator
./os_simulator

Architecture

Kernel

Top-level owner of the three subsystems below. Doesn't contain logic itself — it composes ProcessManager, MemoryManager, and IOManager and exposes a simple interface (boot(), runProcessScheduling(), printAllReports()) so main.cpp doesn't need to know the internal wiring.

ProcessManager + Scheduler (process management)

  • Process is the PCB (Process Control Block) — PID, state, arrival time, burst time, remaining time, priority, and MLFQ queue level.
  • Scheduler is an abstract base class exposing pickNext() and timeSlice(). Five concrete strategies implement it: FCFSScheduler, SJFScheduler, RRScheduler, PriorityScheduler, MLFQScheduler.
  • ProcessManager holds a Scheduler*, not a concrete scheduler type. It runs a time-driven simulation loop: admit arrivals → ask the scheduler who runs next → simulate a context switch → advance time → check completion or requeue. It has zero knowledge of which algorithm is plugged in.

MemoryManager + Pager (memory management)

  • MemoryManager owns a fixed pool of physical frames and tracks which are free/occupied.
  • Pager is a per-process page table, mapping logical pages to physical frames. Each process gets its own Pager instance.
  • allocate()/deallocate() simulate a process acquiring and releasing memory, with a free-frame count that visibly shrinks and recovers.

IOManager + DeviceManager (I/O management)

  • DeviceManager tracks named devices (e.g. Disk, Printer) and which PID currently owns each one.
  • IOManager queues incoming I/O requests and services them one at a time, re-queuing a request if the requested device is busy — a simplified model of blocking I/O and device contention.

Output

The program runs the same 4-process workload (P1–P4, arriving at times 0/1/2/3 with bursts of 8/4/9/5) through all five schedulers back-to-back, then runs a separate Kernel integration demo combining scheduling, memory allocation, and I/O device contention.

--- FCFS Scheduling Report ---
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       8           0         8
2     P2        1         4       12          7         11
3     P3        2         9       21          10        19
4     P4        3         5       26          18        23
Average Waiting Time:    8.75
Average Turnaround Time: 15.25
Context Switches:        4

--- SJF Scheduling Report ---
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       8           0         8
2     P2        1         4       12          7         11
3     P3        2         9       26          15        24
4     P4        3         5       17          9         14
Average Waiting Time:    7.75
Average Turnaround Time: 14.25
Context Switches:        4

--- Round Robin Scheduling Report --- (quantum = 3)
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       23          15        23
2     P2        1         4       16          11        15
3     P3        2         9       26          15        24
4     P4        3         5       21          13        18
Average Waiting Time:    13.5
Average Turnaround Time: 20
Context Switches:        10

--- Priority Scheduling Report ---
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       8           0         8
2     P2        1         4       17          12        16
3     P3        2         9       26          15        24
4     P4        3         5       13          5         10
Average Waiting Time:    8
Average Turnaround Time: 14.5
Context Switches:        4

--- MLFQ Scheduling Report --- (levels: quantum 2, 4, 8)
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       23          15        23
2     P2        1         4       14          9         13
3     P3        2         9       26          15        24
4     P4        3         5       21          13        18
Average Waiting Time:    13
Average Turnaround Time: 19.5
Context Switches:        10

========== Kernel Integration Demo ==========
========================================
   Simulated Kernel Booting...
========================================
[IOManager] PID 1 requested Disk
[IOManager] PID 2 requested Disk
[DeviceManager] Disk granted to PID 1
[DeviceManager] Disk busy (held by PID 1), PID 2 must wait

--- Round Robin Scheduling Report ---
PID   Name      Arrival   Burst   Completion  Waiting   Turnaround
1     P1        0         8       23          15        23
2     P2        1         4       16          11        15
3     P3        2         9       26          15        24
4     P4        3         5       21          13        18
Average Waiting Time:    13.5
Average Turnaround Time: 20
Context Switches:        10

[MemoryManager] Frames: XXXXXXXXXXX.....  (5/16 free)
[DeviceManager] Status: Printer=free  Disk=PID1
[MemoryManager] Frames: ................  (16/16 free)

Reading the results

  • SJF gives the lowest average waiting time (7.75) of all five — expected, since SJF is provably optimal for minimizing average waiting time when all processes are available together, at the cost of potentially starving longer jobs.
  • FCFS and SJF and Priority all show only 4 context switches — each is non-preemptive here, so once a process starts running it runs to completion, one switch per process.
  • RR and MLFQ show 10 context switches — both are preemptive (fixed quantum for RR, per-level quantum for MLFQ), so long processes get interrupted and resumed multiple times. This is the classic fairness vs. overhead tradeoff: RR/MLFQ are more responsive to short jobs but pay for it in extra context-switch overhead and slightly higher average waiting time (13.5 and 13) compared to FCFS/SJF/Priority.
  • The Kernel Integration Demo shows all three subsystems interacting: memory is allocated per-process before scheduling starts (frame count drops from 16 free to 5 free as P1–P4 claim 3+2+4+2 = 11 frames), the IOManager grants the Disk to PID 1 and correctly queues PID 2's request since the device is busy (mutual exclusion in action), and after scheduling completes, memory is deallocated and all 16 frames return to free — confirming no memory leaks in the simulation itself.

Project structure

os-simulator/
├── include/          # class headers
├── src/               # implementations
├── main.cpp           # demo workload + kernel integration demo
└── README.md

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages