Skip to content

Commit 1035bea

Browse files
authored
Add files via upload
1 parent a46d56e commit 1035bea

37 files changed

Lines changed: 2777 additions & 0 deletions
Binary file not shown.
14.2 KB
Binary file not shown.
Binary file not shown.
7.95 KB
Binary file not shown.
2.14 KB
Binary file not shown.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import customtkinter as ctk
2+
import tkinter as tk
3+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
4+
from matplotlib.figure import Figure
5+
import random
6+
7+
# Global logging variable where any module can push messages
8+
_global_logger = None
9+
10+
def push_log(module_name, message):
11+
if _global_logger:
12+
_global_logger(module_name, message)
13+
14+
def create_architecture_tab(parent_frame, nav_callbacks):
15+
card = ctk.CTkFrame(parent_frame, fg_color="#F9FAFB", corner_radius=12)
16+
card.grid(row=0, column=0, sticky="nsew")
17+
card.grid_rowconfigure(0, weight=1)
18+
card.grid_columnconfigure(0, weight=2)
19+
card.grid_columnconfigure(1, weight=1)
20+
21+
left_frame = ctk.CTkFrame(card, fg_color="#FFFFFF", corner_radius=12)
22+
left_frame.grid(row=0, column=0, sticky="nsew", padx=15, pady=15)
23+
24+
ctk.CTkLabel(left_frame, text="OS Architecture Layout", font=ctk.CTkFont(size=18, weight="bold"), text_color="#111827").pack(pady=(15, 0))
25+
ctk.CTkLabel(left_frame, text="Click on a layer to navigate to its simulation module.", font=ctk.CTkFont(size=12), text_color="#6B7280").pack(pady=(0, 10))
26+
27+
canvas = tk.Canvas(left_frame, bg="#FFFFFF", highlightthickness=0)
28+
canvas.pack(fill="both", expand=True, padx=20, pady=10)
29+
30+
layers = [
31+
{"name": "User Space", "color": "#E5E7EB", "text": "#374151", "target": None},
32+
{"name": "System Call Interface", "color": "#D1D5DB", "text": "#1F2937", "target": None},
33+
{"name": "Process Management", "color": "#10B981", "text": "#FFFFFF", "target": "cpu"},
34+
{"name": "Process Synchronization", "color": "#8B5CF6", "text": "#FFFFFF", "target": "sync"},
35+
{"name": "Deadlock Handling", "color": "#EF4444", "text": "#FFFFFF", "target": "deadlock"},
36+
{"name": "Memory & File Systems", "color": "#F59E0B", "text": "#FFFFFF", "target": "fs"},
37+
{"name": "Device Drivers (I/O)", "color": "#3B82F6", "text": "#FFFFFF", "target": "disk"},
38+
{"name": "Hardware", "color": "#111827", "text": "#FFFFFF", "target": "factory"}
39+
]
40+
41+
layer_rects = {}
42+
43+
def draw_architecture():
44+
canvas.delete("all")
45+
canvas.update()
46+
w = canvas.winfo_width()
47+
h = canvas.winfo_height()
48+
if w < 100: w = 400
49+
if h < 100: h = 400
50+
51+
box_h = h / len(layers) - 5
52+
y = 5
53+
54+
for layer in layers:
55+
rect = canvas.create_rectangle(10, y, w-10, y+box_h, fill=layer["color"], outline="", tags=layer["name"])
56+
canvas.create_text(w/2, y + box_h/2, text=layer["name"], fill=layer["text"], font=("Arial", 14, "bold"), tags=layer["name"])
57+
58+
layer_rects[layer["name"]] = rect
59+
60+
if layer["target"]:
61+
def make_handler(target):
62+
return lambda e: nav_callbacks.get(target, lambda: None)()
63+
canvas.tag_bind(layer["name"], "<Button-1>", make_handler(layer["target"]))
64+
canvas.tag_bind(layer["name"], "<Enter>", lambda e, r=rect, c=layer["color"]: canvas.itemconfig(r, fill="#4B5563"))
65+
canvas.tag_bind(layer["name"], "<Leave>", lambda e, r=rect, c=layer["color"]: canvas.itemconfig(r, fill=c))
66+
67+
y += box_h + 5
68+
69+
parent_frame.after(100, draw_architecture)
70+
71+
# Right side: Kernel Status
72+
right_frame = ctk.CTkFrame(card, fg_color="transparent")
73+
right_frame.grid(row=0, column=1, sticky="nsew", padx=(0, 15), pady=15)
74+
right_frame.grid_rowconfigure(0, weight=1)
75+
right_frame.grid_rowconfigure(1, weight=1)
76+
77+
# Kernel Log
78+
log_frame = ctk.CTkFrame(right_frame, fg_color="#FFFFFF", corner_radius=12)
79+
log_frame.grid(row=0, column=0, sticky="nsew", pady=(0, 10))
80+
ctk.CTkLabel(log_frame, text="Kernel Log Console", font=ctk.CTkFont(size=14, weight="bold"), text_color="#111827").pack(anchor="w", padx=15, pady=10)
81+
82+
log_box = tk.Text(log_frame, font=("Courier", 11), bg="#111827", fg="#10B981", relief="flat", highlightthickness=0)
83+
log_box.pack(fill="both", expand=True, padx=15, pady=(0, 15))
84+
85+
global _global_logger
86+
def handle_log(module, msg):
87+
log_box.insert(tk.END, f"[{module}] {msg}\n")
88+
log_box.see(tk.END)
89+
_global_logger = handle_log
90+
91+
# Randomizing charts for system aesthetic
92+
graph_frame = ctk.CTkFrame(right_frame, fg_color="#FFFFFF", corner_radius=12)
93+
graph_frame.grid(row=1, column=0, sticky="nsew")
94+
95+
fig = Figure(figsize=(3,2), dpi=100)
96+
fig.patch.set_facecolor('#FFFFFF')
97+
ax = fig.add_subplot(111)
98+
ax.set_facecolor('#FFFFFF')
99+
ax.set_title("System Resource Flow", fontsize=10)
100+
ax.axis('off')
101+
102+
graph_canvas = FigureCanvasTkAgg(fig, master=graph_frame)
103+
graph_canvas.get_tk_widget().pack(fill="both", expand=True, padx=10, pady=10)
104+
105+
line1, = ax.plot([], [], color="#3B82F6", linewidth=2)
106+
line2, = ax.plot([], [], color="#10B981", linewidth=2)
107+
ax.set_xlim(0, 20)
108+
ax.set_ylim(0, 100)
109+
110+
cpu_data = [random.randint(20, 40) for _ in range(21)]
111+
mem_data = [random.randint(50, 80) for _ in range(21)]
112+
113+
def update_graph():
114+
cpu_data.pop(0)
115+
cpu_data.append(random.randint(20, 90))
116+
mem_data.pop(0)
117+
mem_data.append(random.randint(50, 95))
118+
119+
line1.set_data(range(21), cpu_data)
120+
line2.set_data(range(21), mem_data)
121+
graph_canvas.draw()
122+
parent_frame.after(1000, update_graph)
123+
124+
update_graph()
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import customtkinter as ctk
2+
import tkinter as tk
3+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
4+
from matplotlib.figure import Figure
5+
import time
6+
7+
def create_cpu_tab(parent_frame):
8+
card = ctk.CTkFrame(parent_frame, fg_color="#FFFFFF", corner_radius=12)
9+
card.grid(row=0, column=0, sticky="nsew")
10+
card.grid_rowconfigure(2, weight=1)
11+
card.grid_columnconfigure(0, weight=1)
12+
13+
top_frame = ctk.CTkFrame(card, fg_color="transparent")
14+
top_frame.grid(row=0, column=0, sticky="ew", padx=20, pady=10)
15+
ctk.CTkLabel(top_frame, text="CPU Scheduling & Analytics", font=ctk.CTkFont(size=18, weight="bold"), text_color="#111827").pack(side="left")
16+
17+
# Layout: Top is Queues & Gantt, Bottom is Graph & Stats
18+
visual_frame = ctk.CTkFrame(card, fg_color="transparent")
19+
visual_frame.grid(row=1, column=0, sticky="nsew", padx=20)
20+
21+
ctk.CTkLabel(visual_frame, text="Ready Queue (Process Creation)", font=ctk.CTkFont(size=14, weight="bold"), text_color="#374151").pack(anchor="w", pady=(10,0))
22+
queue_canvas = tk.Canvas(visual_frame, height=80, bg="#F9FAFB", highlightthickness=1, highlightbackground="#E5E7EB")
23+
queue_canvas.pack(fill="x", pady=5)
24+
25+
ctk.CTkLabel(visual_frame, text="Execution Gantt Chart", font=ctk.CTkFont(size=14, weight="bold"), text_color="#374151").pack(anchor="w", pady=(10,0))
26+
cv = tk.Canvas(visual_frame, height=120, bg="#F9FAFB", highlightthickness=1, highlightbackground="#E5E7EB")
27+
cv.pack(fill="x", pady=5)
28+
29+
bottom_frame = ctk.CTkFrame(card, fg_color="transparent")
30+
bottom_frame.grid(row=2, column=0, sticky="nsew", padx=20, pady=10)
31+
bottom_frame.grid_columnconfigure(0, weight=1)
32+
bottom_frame.grid_columnconfigure(1, weight=1)
33+
34+
# Graph Area
35+
graph_parent = ctk.CTkFrame(bottom_frame, fg_color="transparent")
36+
graph_parent.grid(row=0, column=0, sticky="nsew", padx=(0,10))
37+
fig = Figure(figsize=(4,3), dpi=100)
38+
fig.patch.set_facecolor('#F9FAFB')
39+
ax = fig.add_subplot(111)
40+
ax.set_facecolor('#FFFFFF')
41+
ax.set_title("Real-Time Waiting Time Trend")
42+
ax.set_ylabel("Waiting Time")
43+
ax.set_xlabel("Process Index")
44+
graph_canvas = FigureCanvasTkAgg(fig, master=graph_parent)
45+
graph_canvas.draw()
46+
graph_canvas.get_tk_widget().pack(fill="both", expand=True)
47+
48+
# Stats Area
49+
stats_frame = ctk.CTkFrame(bottom_frame, fg_color="#F9FAFB", corner_radius=8, border_width=1, border_color="#E5E7EB")
50+
stats_frame.grid(row=0, column=1, sticky="nsew", padx=(10,0))
51+
ctk.CTkLabel(stats_frame, text="Simulation Output", font=ctk.CTkFont(weight="bold"), text_color="#111827").pack(pady=10)
52+
result_box = tk.Text(stats_frame, height=10, width=30, font=("Courier", 11), bg="#F9FAFB", fg="#111827", relief="flat")
53+
result_box.pack(fill="both", expand=True, padx=10, pady=10)
54+
55+
processes = [
56+
{"id": "P1", "burst": 4, "priority": 2},
57+
{"id": "P2", "burst": 3, "priority": 1},
58+
{"id": "P3", "burst": 5, "priority": 3}
59+
]
60+
61+
def draw_queue(procs):
62+
queue_canvas.delete("all")
63+
x = 20
64+
for p in procs:
65+
queue_canvas.create_rectangle(x, 20, x+60, 60, fill="#FFD166", outline="#F59E0B", width=2)
66+
queue_canvas.create_text(x+30, 40, text=p["id"], font=("Arial", 11, "bold"), fill="#78350F")
67+
x += 80
68+
69+
def calculate_waiting_times(procs):
70+
waiting_times = []
71+
for i, p in enumerate(procs):
72+
if i == 0:
73+
waiting_times.append(0)
74+
else:
75+
wait = sum(prev["burst"] for prev in procs[:i])
76+
waiting_times.append(wait)
77+
return waiting_times
78+
79+
def update_graph(waiting_times):
80+
ax.clear()
81+
ax.plot(waiting_times, marker='o', color="#1F4ED8")
82+
ax.set_title("Real-Time Waiting Time Trend")
83+
ax.set_ylabel("Waiting Time")
84+
ax.set_xlabel("Process Index")
85+
graph_canvas.draw()
86+
87+
def simulate(algo="FCFS"):
88+
cv.delete("all")
89+
result_box.delete("1.0", tk.END)
90+
cv.update()
91+
queue_canvas.update()
92+
w = cv.winfo_width()
93+
94+
procs = processes.copy()
95+
96+
if algo == "Priority":
97+
procs.sort(key=lambda x: x["priority"])
98+
elif algo == "SJF":
99+
procs.sort(key=lambda x: x["burst"])
100+
101+
y_pos = 60
102+
cv.create_line(50, y_pos+30, w-50, y_pos+30, fill="#E5E7EB", width=2)
103+
104+
wait_times = calculate_waiting_times(procs)
105+
106+
# Process Creation Animation (Move to Ready Queue)
107+
queue_canvas.delete("all")
108+
109+
def animate_creation(idx=0):
110+
if idx < len(procs):
111+
p = procs[idx]
112+
x_start = -50
113+
x_end = 20 + (idx * 80)
114+
115+
rect = queue_canvas.create_rectangle(x_start, 20, x_start+60, 60, fill="#4CAF50", outline="#22C55E", width=2)
116+
txt = queue_canvas.create_text(x_start+30, 40, text=p["id"], font=("Arial", 11, "bold"), fill="#14532D")
117+
118+
def slide(cx):
119+
if cx < x_end:
120+
queue_canvas.move(rect, 15, 0)
121+
queue_canvas.move(txt, 15, 0)
122+
parent_frame.after(30, lambda: slide(cx+15))
123+
else:
124+
animate_creation(idx+1)
125+
slide(x_start)
126+
else:
127+
# Proceed to Gantt rendering
128+
run_gantt()
129+
130+
def run_gantt():
131+
x = 50
132+
index = 0
133+
live_waits = []
134+
135+
def step():
136+
nonlocal x, index
137+
if index < len(procs):
138+
p = procs[index]
139+
width = p["burst"] * 30
140+
141+
# Update Ready Queue visually (remove process)
142+
draw_queue(procs[index+1:])
143+
144+
# Draw Block
145+
cv.create_rectangle(x, y_pos-30, x+width, y_pos+30, fill="#10B981", outline="#059669", width=2)
146+
cv.create_text(x+width/2, y_pos, text=p["id"], font=("Arial", 12, "bold"), fill="#064E3B")
147+
148+
# Draw Time Ticks
149+
cv.create_text(x, y_pos+45, text=str(sum(pr["burst"] for pr in procs[:index])), font=("Arial", 10), fill="#6B7280")
150+
if index == len(procs) - 1:
151+
cv.create_text(x+width, y_pos+45, text=str(sum(pr["burst"] for pr in procs)), font=("Arial", 10), fill="#6B7280")
152+
153+
live_waits.append(wait_times[index])
154+
update_graph(live_waits)
155+
156+
result_box.insert(tk.END, f"{algo} -> Executed {p['id']} (Wait: {wait_times[index]})\n")
157+
158+
x += width
159+
index += 1
160+
parent_frame.after(1000, step)
161+
else:
162+
avg_wait = sum(wait_times)/len(wait_times)
163+
avg_ta = sum(wait_times[i] + procs[i]["burst"] for i in range(len(procs))) / len(procs)
164+
result_box.insert(tk.END, f"\nAvg Waiting Time: {avg_wait:.2f}\n")
165+
result_box.insert(tk.END, f"Avg Turnaround: {avg_ta:.2f}\n")
166+
167+
step()
168+
169+
animate_creation()
170+
171+
def simulate_starvation():
172+
cv.delete("all")
173+
queue_canvas.delete("all")
174+
result_box.delete("1.0", tk.END)
175+
result_box.insert(tk.END, "Low priority process P5 waiting...\n")
176+
177+
draw_queue([{"id": "P5", "burst": 2, "priority": 10}])
178+
179+
def sim_starve():
180+
result_box.insert(tk.END, "-> High priority P1 arrived and executed\n")
181+
result_box.insert(tk.END, "-> High priority P2 arrived and executed\n")
182+
result_box.insert(tk.END, "-> High priority P3 arrived and executed\n")
183+
result_box.insert(tk.END, "\n⚠ Starvation occurred:\n P5 never executed due to continuous high-priority arrivals.\n")
184+
result_box.see(tk.END)
185+
186+
parent_frame.after(1500, sim_starve)
187+
188+
189+
btn_frame = ctk.CTkFrame(card, fg_color="transparent")
190+
btn_frame.grid(row=3, column=0, sticky="ew", padx=20, pady=10)
191+
192+
ctk.CTkButton(btn_frame, text="FCFS", fg_color="#10B981", hover_color="#059669", command=lambda: simulate("FCFS"), width=100).pack(side="left", padx=5)
193+
ctk.CTkButton(btn_frame, text="SJF", fg_color="#F59E0B", hover_color="#D97706", command=lambda: simulate("SJF"), width=100).pack(side="left", padx=5)
194+
ctk.CTkButton(btn_frame, text="Priority", fg_color="#8B5CF6", hover_color="#7C3AED", command=lambda: simulate("Priority"), width=100).pack(side="left", padx=5)
195+
ctk.CTkButton(btn_frame, text="Starvation Demo", fg_color="#EF4444", hover_color="#DC2626", command=simulate_starvation, width=150).pack(side="left", padx=5)
2.82 KB
Binary file not shown.
2.87 KB
Binary file not shown.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import numpy as np
2+
import time
3+
4+
def bankers_algorithm(available, max_matrix, allocation):
5+
"""
6+
Simulates the Banker's Algorithm to find if the system is in a safe state.
7+
Returns: (is_safe, safe_sequence)
8+
"""
9+
n = len(allocation) # num processes
10+
11+
# Calculate Need matrix
12+
need = np.array(max_matrix) - np.array(allocation)
13+
work = np.array(available).copy()
14+
finish = [False] * n
15+
safe_sequence = []
16+
17+
while True:
18+
found = False
19+
for i in range(n):
20+
if not finish[i] and all(need[i] <= work):
21+
# Process can finish
22+
work += np.array(allocation[i])
23+
finish[i] = True
24+
safe_sequence.append(f"P{i}")
25+
found = True
26+
if not found:
27+
break
28+
29+
if all(finish):
30+
return True, safe_sequence
31+
else:
32+
return False, safe_sequence
33+
34+
def bankers_with_steps(available, max_matrix, allocation, callback):
35+
n = len(allocation) # num processes
36+
37+
# Calculate Need matrix
38+
need = np.array(max_matrix) - np.array(allocation)
39+
work = np.array(available).copy()
40+
finish = [False] * n
41+
safe_sequence = []
42+
43+
callback({"type": "init", "work": list(work), "need": need.tolist(), "alloc": allocation, "finish": finish})
44+
time.sleep(1)
45+
46+
while True:
47+
found = False
48+
for i in range(n):
49+
if not finish[i] and all(need[i] <= work):
50+
callback({"type": "checking", "proc": i, "work": list(work), "finish": finish})
51+
time.sleep(1)
52+
53+
work += np.array(allocation[i])
54+
finish[i] = True
55+
safe_sequence.append(f"P{i}")
56+
57+
callback({"type": "finished_step", "proc": i, "work": list(work), "finish": finish})
58+
time.sleep(1)
59+
found = True
60+
61+
if not found:
62+
break
63+
64+
if all(finish):
65+
callback({"type": "success", "sequence": safe_sequence, "finish": finish})
66+
else:
67+
callback({"type": "deadlock", "finish": finish})

0 commit comments

Comments
 (0)