Operating System Concepts

Processes, threads, memory, scheduling, deadlocks, file systems & networking fundamentals

Core CS + Interview
Contents
⚙️

Processes

A process is a running instance of a program. It has its own memory space, file descriptors, and resources.

Process States

┌─────────┐ create ──→ │ New │ └────┬────┘ ↓ ┌─────────┐ schedule ┌─────────────┐ │ Ready │ ──────────────→ │ Running │ └────┬────┘ ←────────────── └──────┬──────┘ ↑ preempt / yield │ │ ↓ │ ┌──────────┐ └─── I/O complete ────── │ Waiting │ └──────────┘ │ The process terminates from ↓ Running state ──────────────→ ┌────────────┐ │ Terminated │ └────────────┘

Process Control Block (PCB)

OS maintains a PCB for each process containing:

Inter-Process Communication (IPC)

MethodDescriptionUse Case
PipeUnidirectional byte stream between parent/childShell pipes: ls | grep
Named Pipe (FIFO)Pipe with a name in filesystem, unrelated processesSimple IPC between processes
Message QueueStructured messages via kernel-managed queueDecoupled communication
Shared MemoryMultiple processes access same memory regionHigh-speed data sharing (fastest)
SocketNetwork or local communication endpointClient-server, network apps
SignalAsync notification (SIGTERM, SIGKILL, etc.)Process control (kill, stop)
🧵

Threads

A thread is a lightweight execution unit within a process. Threads in the same process share memory and resources.

What Threads Share vs Own

Shared (per process)

  • Code section (text)
  • Heap memory
  • Global variables
  • File descriptors
  • Signal handlers

Own (per thread)

  • Thread ID
  • Stack (local variables)
  • Program counter
  • CPU registers
  • Thread-local storage

Threading Models

ModelDescriptionExample
1:1 (Kernel threads)Each user thread maps to one kernel threadLinux pthreads, Java threads
N:1 (User threads)Many user threads → one kernel threadGreen threads (early Java)
M:N (Hybrid)M user threads → N kernel threadsGo goroutines, Erlang processes
⚖️

Process vs Thread

AspectProcessThread
MemorySeparate address spaceShared address space
Creation costExpensive (fork)Cheap
Context switchSlow (TLB flush, page tables)Fast (shared memory)
CommunicationIPC (pipes, sockets, shared mem)Direct memory access
Crash impactIsolated — one crash doesn't affect othersOne crash can kill entire process
SecurityStrong isolationWeak — any thread can corrupt shared data
💡 When to use which?
  • Processes: Need isolation, security, fault tolerance (e.g., Chrome tabs, microservices)
  • Threads: Need shared state, high performance, responsive UI (e.g., web servers, UI threads)
  • Async/Event loop: I/O-bound work without true parallelism (Node.js, Python asyncio)
📅

CPU Scheduling

The OS schedule determines which process/thread runs on the CPU and for how long.

Key Metrics

Scheduling Algorithms

AlgorithmPreemptive?How It WorksPros / Cons
FCFSNoFirst Come, First ServedSimple. Convoy effect (short jobs wait behind long ones).
SJFNoShortest Job FirstOptimal avg waiting time. Hard to predict burst time. Starvation possible.
SRTFYesShortest Remaining Time FirstPreemptive SJF. Better response. Still prone to starvation.
Round RobinYesEach process gets a time quantum (e.g., 10ms)Fair, good response. Performance depends on quantum size.
PriorityBothHigher priority runs firstImportant tasks first. Starvation → fix with aging.
Multilevel QueueYesSeparate queues for different priority classesFlexible. Used in real systems (foreground vs background).
CFS (Linux)YesCompletely Fair Scheduler — red-black tree, virtual runtimeFair, O(log n) scheduling. Default in modern Linux.
🔒

Synchronization

When multiple threads/processes access shared resources, we need synchronization to prevent race conditions.

Critical Section Problem

A critical section is code that accesses shared resources. Requirements for a correct solution:

Synchronization Primitives

PrimitiveDescriptionUse Case
Mutex (Lock)Binary lock — only the owner can unlockProtecting shared data (one writer at a time)
SemaphoreCounter-based — allows N concurrent accessorsConnection pool, rate limiting
Condition VariableWait until a condition is true (used with mutex)Producer-consumer pattern
Read-Write LockMultiple readers OR one writerRead-heavy workloads (caches, config)
SpinlockBusy-wait loop instead of sleepingVery short critical sections (kernel)
Atomic operationsHardware-level indivisible operations (CAS)Lock-free data structures, counters

Classic Problems

💀

Deadlocks

A deadlock occurs when two or more processes are waiting for each other to release resources, and none can proceed.

Four Necessary Conditions (Coffman)

All four must hold simultaneously for deadlock:

  1. Mutual Exclusion: Resource held exclusively by one process
  2. Hold and Wait: Process holds resource while waiting for another
  3. No Preemption: Resources can't be forcibly taken away
  4. Circular Wait: Circular chain of processes each waiting for the next's resource

Handling Deadlocks

StrategyHowTrade-off
PreventionBreak one of the four conditions (e.g., ordered resource acquisition)Restricts system, may reduce concurrency
AvoidanceBanker's algorithm — check if granting resource is safeRequires advance knowledge of max needs
Detection & RecoveryBuild wait-for graph, detect cycles, kill a processOverhead of detection; may lose work
Ignore (Ostrich)Assume deadlocks are rare, reboot if it happensUsed in most real systems (Linux, Windows)
🧠

Memory Management

Memory Layout of a Process

High Address ───────────────────────────── │ Stack │ ← grows downward (local vars, return addr) │ ↓ │ │ (free space) │ │ ↑ │ │ Heap │ ← grows upward (malloc, new) │──────────────────────────── │ │ Uninitialized Data (BSS) │ ← global vars = 0 │ Initialized Data (.data) │ ← global vars with values │ Text (Code) │ ← compiled machine code (read-only) Low Address ─────────────────────────────

Memory Allocation

TypeWhereLifetimeSpeed
StackStack segmentFunction scope (auto)Very fast (pointer bump)
HeapHeap segmentUntil explicitly freedSlower (malloc/free overhead)
Static/GlobalData/BSS segmentEntire program lifetimeAllocated at load time

Fragmentation

💾

Virtual Memory

Each process gets its own virtual address space mapped to physical memory via page tables.

How It Works

Page Fault

When a process accesses a page not in physical memory:

  1. CPU generates a page fault interrupt
  2. OS checks if the access is valid (segfault if not)
  3. OS finds a free frame (or evicts a page using replacement algorithm)
  4. OS reads the page from disk into the frame
  5. OS updates the page table and restarts the instruction

Benefits

🔄

Page Replacement Algorithms

When physical memory is full and a new page is needed, which page do we evict?

AlgorithmHow It WorksPros / Cons
FIFOEvict the oldest pageSimple. Belady's anomaly (more frames can cause more faults).
Optimal (OPT)Evict page not used for longest time in futureBest possible. Impossible in practice (requires future knowledge).
LRUEvict least recently used pageClose to optimal. Expensive to implement perfectly.
Clock (Second Chance)FIFO with reference bit — give each page a second chanceGood approximation of LRU. Used in real systems.
LFUEvict least frequently used pageWorks well for stable access patterns.
🔑 Thrashing: When a process spends more time swapping pages than executing. Happens when working set exceeds available frames. Fix: increase memory, reduce multiprogramming, use better page replacement.
📂

File Systems

Common File Systems

FSOSMax FileFeatures
ext4Linux16 TBJournaling, extents, default Linux FS
XFSLinux8 EBHigh performance, parallel I/O
NTFSWindows16 EBACLs, compression, encryption
APFSmacOS8 EBCopy-on-write, snapshots, encryption
ZFSMulti16 EBData integrity, snapshots, RAID built-in

Key Concepts

💿

I/O & Storage

I/O Models

ModelDescriptionUsed By
Blocking I/OThread waits until I/O completesTraditional (one thread per connection)
Non-blocking I/OReturns immediately if not ready, poll againBusy-wait loop
I/O Multiplexingselect()/poll()/epoll() — wait on multiple FDsNginx, Node.js, Redis
Async I/OKernel notifies when I/O is doneio_uring (Linux), IOCP (Windows)

Storage Comparison

TypeSpeedCostUse Case
RAM~100 ns$$$Active data, caches
NVMe SSD~10 μs$$Databases, OS
SATA SSD~50 μs$$General storage
HDD~2 ms$Archives, backups
🌐

Networking Basics

OSI Model (7 Layers)

#LayerProtocolWhat It Does
7ApplicationHTTP, DNS, FTP, SMTPUser-facing protocols
6PresentationSSL/TLS, JPEGEncryption, encoding, compression
5SessionNetBIOS, RPCSession management
4TransportTCP, UDPReliable delivery, ports
3NetworkIP, ICMPRouting, IP addressing
2Data LinkEthernet, Wi-FiMAC addresses, frames
1PhysicalCables, radioBits on the wire

TCP vs UDP

FeatureTCPUDP
ConnectionConnection-oriented (3-way handshake)Connectionless
ReliabilityGuaranteed delivery, ordering, retransmitNo guarantees (fire-and-forget)
SpeedSlower (overhead)Faster (minimal overhead)
Use caseWeb (HTTP), email, file transferVideo streaming, gaming, DNS

DNS Resolution Flow

Browser → Local DNS Cache → OS DNS Cache → Recursive Resolver → Root Server (.com) → TLD Server (google.com) → Authoritative Server → Returns IP → Browser connects via TCP

HTTP/HTTPS

🐧

Linux Essentials

# Process management
ps aux                    # list all processes
top / htop                # interactive process viewer
kill -9 <pid>             # force kill process
kill -15 <pid>            # graceful termination (SIGTERM)
nohup ./app &             # run in background, survives logout
jobs / fg / bg             # job control

# Memory & Disk
free -h                   # memory usage
df -h                     # disk space
du -sh /path              # directory size
lsof -i :8080             # what's using port 8080

# File permissions
chmod 755 file            # rwxr-xr-x
chown user:group file     # change ownership
# r=4 w=2 x=1 → owner|group|other

# Networking
netstat -tlnp             # listening ports
ss -tlnp                  # modern netstat
curl -v https://api.com   # HTTP request with headers
dig google.com            # DNS lookup
traceroute google.com     # network path

# Useful combos
grep -r "pattern" /path   # recursive search
find / -name "*.log" -mtime -1  # files modified in last day
tail -f /var/log/app.log  # follow log in real-time
awk '{print $1}' file     # print first column
wc -l file                # count lines