The Five Generations of Operating Systems
Animated Timeline — 80 Years of OS Evolution
1.1 Generation 1 (1945–1955) — Vacuum Tubes, No OS
Machines like ENIAC and UNIVAC I filled entire rooms. A programmer physically rewired plugboards or fed punched cards for every program. There was no operating system, no library, no compiler — just the programmer and raw hardware. Machine failures happened every few minutes because vacuum tubes burned out.
1.2 Generation 2 (1955–1965) — Transistors and Batch Systems
Transistors replaced tubes, making machines smaller and more reliable. Programs were still submitted as decks of punched cards, but an operator collected them into batches and ran them one after another. This gave birth to the first real operating systems — FMS (Fortran Monitor System) and IBM's IBSYS. FORTRAN and COBOL emerged as programming languages.
1.3 Generation 3 (1965–1980) — Integrated Circuits, Multiprogramming
Integrated circuits dramatically shrank hardware. IBM's OS/360 introduced the idea of one OS running across an entire product family. MULTICS pioneered time-sharing; its lessons produced UNIX at Bell Labs in 1969. Key concepts born here: multiprogramming, virtual memory, spooling, time-sharing, minicomputers.
1.4 Generation 4 (1980–2000) — Personal Computers and GUI
VLSI put a full CPU on a single chip. MS-DOS (1981), the Apple Macintosh (1984), Windows 3.1 (1992), and Linux (1991) put a computer on every desk. Xerox PARC's WIMP interface (Windows, Icons, Menus, Pointer) became mainstream. TCP/IP networking made network operating systems possible.
1.5 Generation 5 (2000–Present) — Mobile, Cloud, and AI
iOS (2007) and Android (2008) made touch the primary input. Cloud OS platforms (AWS, Azure, GCP) turned data centers into rentable slices. Container orchestration (Kubernetes) treats thousands of servers as one machine. AI-assisted schedulers, predictive prefetching, and secure enclaves define the current frontier.
Every generation moved computing closer to the user and further from the hardware. First programmers were the OS. Then the OS mediated. Now the OS is invisible — you tap an icon and everything just works.
System Boot — From Power Button to Login Screen
When you press the power button, your computer has no idea what an OS is. Getting from "electricity flowing" to "here's your desktop" is a carefully choreographed boot sequence. Galvin calls the small program that starts it all the bootstrap program.
Animated Boot Flow — Six Stages, Each Bootstrapping the Next
2.1 BIOS vs UEFI — The Firmware Layer
| 16-bit real mode, 1 MB RAM limit |
| Boots from MBR — first 512 bytes of disk |
| Max disk size 2 TB (32-bit LBA) |
| No Secure Boot, no GUI setup |
| Text menu, keyboard-only navigation |
| 64-bit, uses full RAM & hardware |
| Boots from EFI System Partition (.efi files) |
| Disk size up to 9.4 ZB (via GPT) |
| Secure Boot — cryptographic signature checks |
| GUI setup, mouse support, network boot |
2.2 Practical — Observe Your Own Boot Sequence
# Linux — see kernel messages from the boot sequence
$ dmesg | head -20
[ 0.000000] Linux version 6.5.0-15-generic (gcc 11.4.0)
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz root=UUID=... ro quiet
[ 0.043210] ACPI: Early table checksum verification disabled
[ 0.145678] smpboot: CPU0: Intel(R) Core(TM) i7-12700H
[ 0.789012] usb 1-1: new high-speed USB device number 2
# How long each stage took
$ systemd-analyze
Startup finished in 2.851s (kernel) + 4.213s (userspace) = 7.064s
graphical.target reached after 4.198s in userspace
# Which services were the slowest to start
$ systemd-analyze blame | head -5
2.410s NetworkManager-wait-online.service
1.184s snapd.service
978ms plymouth-quit-wait.service
542ms systemd-journal-flush.service
318ms udisks2.service
# Are you booted via UEFI or BIOS?
$ [ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"
UEFI
Operating System Services — What the OS Provides
Galvin groups OS services into two families: services that help the user, and services that ensure efficient system operation. Both reach programs through system calls and reach humans through interfaces.
Animated Overview — All OS Services Orbiting the Kernel
| Service | Family | What It Does |
|---|---|---|
| User Interface | User-facing | CLI, GUI, or touch — human ↔ machine |
| Program Execution | User-facing | Load binary, run, terminate cleanly |
| I/O Operations | User-facing | Uniform interface to disk, network, keyboard |
| File-System Manipulation | User-facing | Files, directories, permissions, search |
| Communication | User-facing | Pipes, sockets, shared memory, IPC |
| Error Detection | User-facing | Hardware faults, memory errors, invalid ops |
| Resource Allocation | System-facing | Distribute CPU, RAM, disk among processes |
| Accounting | System-facing | Track usage per user for billing/planning |
| Protection & Security | System-facing | Isolate processes, authenticate users |
User & OS Interface — CLI, GUI, Touch, Voice
Every OS exposes at least one interface for humans. Most modern OSes provide several so users can pick the right tool for the task.
Animated Comparison — Same Task, Different Interfaces
System Calls — The Programmer's Doorway to the Kernel
A system call is the programmatic way a user process asks the OS kernel
to do something on its behalf. It is the only legal path from user mode to kernel
mode — hardware enforces this via a special instruction (syscall on x86-64,
svc on ARM64).
Animated Mode Switch — What Really Happens on write()
You cannot "fake" a mode switch from user code. The syscall instruction
is the only instruction that atomically sets the mode bit to kernel and jumps
to a fixed kernel entry point. Any attempt to modify the mode bit directly from user
space raises a General Protection Fault and the OS kills your process.
5.1 API vs System Call — What You Write vs What Actually Happens
| Layer | What It Is | Example |
|---|---|---|
| Application | Your program | printf("Hi") |
| API (library) | Portable wrapper | glibc write() |
| System call | Actual kernel entry | syscall #1 on Linux x86-64 |
| Kernel routine | Handler | Linux sys_write() |
| Hardware | Device driver | tty driver → terminal |
5.2 How Parameters Are Passed to a Syscall
int 0x80).The Six Categories of System Calls (Galvin)
Every syscall, regardless of OS, falls into one of six functional groups. Learn these six and any kernel's syscall table becomes readable.
Animated View — Syscall Categories Feeding the Kernel
| Category | Purpose | Linux | Windows |
|---|---|---|---|
| Process Control | Create, terminate, wait, load, execute processes | fork(), execve(), wait(), exit() |
CreateProcess(), ExitProcess() |
| File Management | Create, open, read, write, delete, close files | open(), read(), write(), close() |
CreateFile(), ReadFile(), WriteFile() |
| Device Management | Request & release devices, read/write, get/set attributes | ioctl(), read(), write() on /dev/* |
DeviceIoControl() |
| Information Maintenance | Get/set time, date, PID, system data | getpid(), time(), uname() |
GetCurrentProcessId(), GetSystemTime() |
| Communication | Create/delete connections, send/receive messages, shared memory | pipe(), socket(), send(), shmget() |
CreatePipe(), socket() |
| Protection | Control access to resources, set/get permissions | chmod(), chown(), setuid() |
SetFileSecurity() |
6.1 Process Control — fork() and exec() in C
// Classic Galvin fork-exec-wait pattern
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork(); // SYSCALL — clone the process
if (pid == 0) {
printf("Child PID %d\n", getpid());
execlp("ls", "ls", "-l", NULL); // SYSCALL — replace child image
} else {
int status;
wait(&status); // SYSCALL — parent waits
printf("Child finished with status %d\n", status);
}
return 0;
}
6.2 File Management — Reading a File with Raw Syscalls
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open("/etc/hostname", O_RDONLY); // SYSCALL 1
char buf[64];
int n = read(fd, buf, sizeof(buf)); // SYSCALL 2
write(1, buf, n); // SYSCALL 3 (fd 1 = stdout)
close(fd); // SYSCALL 4
return 0;
}
6.3 Communication — Pipe Between Parent and Child
#include <stdio.h>
#include <unistd.h>
int main() {
int fd[2]; pipe(fd); // SYSCALL — create pipe
if (fork() == 0) {
close(fd[0]);
write(fd[1], "Hello parent!\n", 14);
} else {
char buf[64];
close(fd[1]);
int n = read(fd[0], buf, sizeof(buf));
write(1, buf, n);
}
return 0;
}
6.4 Watch Every System Call a Program Makes
# strace shows every syscall + args + return value
$ strace -e trace=openat,read,write,close cat /etc/hostname
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "mohit-laptop\n", 131072) = 13
write(1, "mohit-laptop\n", 13) = 13
close(3) = 0
+++ exited with 0 +++
# Aggregate — how many syscalls of each type
$ strace -c ls / > /dev/null
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
28.14 0.000203 7 27 mmap
19.35 0.000140 6 22 openat
12.06 0.000087 4 22 close
9.98 0.000072 3 21 read
7.34 0.000053 2 19 fstat
------ ----------- ----------- --------- --------- ----------------
100.00 0.000723 120 0 total
System Programs — Between the User and the Syscall
Users rarely make syscalls directly. Instead, they use system programs — utilities bundled with the OS that wrap syscalls in friendly commands. Galvin lists eight common categories.
cp, mv, rm, ls, mkdirdate, ps, top, df, uptimenano, vim, sed, awkgcc, python, make, gdbld, dynamic loader, lddssh, curl, ping, mailsystemd, cron, sshdPractical — Trace echo hi All the Way Down
read() from stdin → File Management syscall.
fork() → Process Control.
execve("/bin/echo", ...) → Process Control. Kernel loads the binary and jumps to its entry point.
write(1, "hi\n", 3) → File Management. Kernel forwards bytes to the terminal driver.
exit_group(0) → Process Control. Kernel reclaims memory.
wait4() returns → Process Control. Prompt reappears.
A one-word echo hi triggered at least six syscalls spanning
two of Galvin's six categories. Every interactive command is a small
conversation between your shell and the kernel.
Golden Rules — What to Remember
syscall instruction and mode bit — user code cannot fake it.
strace (Linux), dtruss (macOS), or Process Monitor (Windows) to see syscalls live. Watching a program's kernel entries is the fastest way to truly understand the OS.