OPERATING SYSTEMS / 8. FULL PICTURE — HARDWARE TO APP
The Full Picture — Tracing One Execution
Following python hello.py from shell command to printed output, at every layer
EXPLANATION
Let's trace exactly what happens when you type "python hello.py" in your terminal, all the way from keystrokes to the printed output. Every layer we've covered plays a role.
The journey of "python hello.py":
HARDWARE → KERNEL (Input):
① Each key press generates an electrical signal → keyboard controller sends interrupt (IRQ1)
② CPU's interrupt controller (APIC) raises interrupt
③ CPU pauses current work → saves registers → jumps to interrupt handler in kernel
④ Keyboard driver reads scancode from I/O port 0x60 → translates to ASCII
⑤ Kernel puts character in terminal's input buffer
⑥ Shell (bash) is blocked in read() syscall waiting for input — kernel wakes it up
SHELL → OS (Process creation):
⑦ Shell reads the line "python hello.py"
⑧ Shell parses: command = "python", argument = "hello.py"
⑨ Shell calls fork() → kernel creates a child process (copies page tables, fd table)
⑩ Child process calls exec("python", ["python", "hello.py"]) syscall
⑪ Kernel: replaces child's address space with python interpreter binary
⑫ Kernel reads python binary from /usr/bin/python (disk → page cache → address space)
⑬ Dynamic linker (/lib/ld-linux.so) maps shared libraries (libc, libpython…)
PYTHON INTERPRETER:
⑭ Python starts — initializes itself, sets up GC, imports sys
⑮ Opens hello.py: open() → VFS → ext4 → disk read → page cache
⑯ Compiles hello.py to bytecode (CPython's front end)
⑰ Python VM executes bytecode instruction by instruction:
• LOAD_GLOBAL (print) → looks up in globals dict
• LOAD_CONST ("Hello, World!") → loads string object
• CALL_FUNCTION → calls print()
KERNEL → HARDWARE (Output):
⑱ print() calls sys.stdout.write("Hello, World!")
⑲ Python's file object buffers the string
⑳ Calls write(fd=1, buf, len) syscall
㉑ Kernel receives write() → checks fd 1 is a tty
㉒ Terminal driver receives bytes → processes escape codes if any
㉓ Characters go to the framebuffer (GPU memory) via display driver
㉔ GPU sends signals to monitor → pixels light up
㉕ You see "Hello, World!" on screen
Process exit:
⑧ Python calls exit(0) syscall
㉖ Kernel: closes all file descriptors, frees address space, stores exit code
㉗ Sends SIGCHLD to parent (shell)
㉘ Shell calls waitpid() → gets exit code 0 → displays prompt again
This entire sequence — from keystroke to display — takes about 50–200 milliseconds. Most of that time is I/O (reading the file, disk access). The actual computation is microseconds. Now you understand every nanosecond of it.DIAGRAM
"python hello.py" — complete trace:
Keyboard HW → IRQ → Kernel ISR → Terminal Driver
↓
Shell reads input
↓
fork() → clone child process
↓
exec() → load python binary
↓
Kernel: map ELF into VM
Dynamic linker: load .so files
↓
Python interpreter starts
open("hello.py") → read bytecode
↓
Execute: LOAD, CALL print()
↓
write(fd=1, "Hello, World!
")
↓
Kernel: tty driver receives bytes
↓
Framebuffer update → GPU → Monitor
↓
YOU SEE: Hello, World!
TIMING (approximate):
Keystroke → kernel: ~0.1 ms
fork() + exec(): ~5 ms
Python startup: ~30 ms
File read + bytecode: ~5 ms
print() → write() syscall: ~0.01 ms
Screen update: ~16 ms (1 frame at 60Hz)CODE